cardbuddy 0.6.0 → 0.8.0

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.
Files changed (36) hide show
  1. package/README.md +21 -0
  2. package/dist/preview-editor/assets/index-BQKzMPBq.js +79 -0
  3. package/dist/preview-editor/assets/index-D3zp47Dg.css +1 -0
  4. package/dist/preview-editor/index.html +2 -2
  5. package/dist/server-core/cardFiles.js +9 -4
  6. package/dist/server-core/codeBridge.js +359 -0
  7. package/dist/server-core/index.js +14 -2
  8. package/dist/server-core/sliceUpload.js +97 -0
  9. package/dist/standalone.js +18 -3
  10. package/dist/vendored/App.vue +268 -45
  11. package/dist/vendored/api.js +102 -32
  12. package/dist/vendored/assets/svgIcons/icons.svg +5 -0
  13. package/dist/vendored/components/ApiCallPanel.vue +127 -0
  14. package/dist/vendored/components/ApiPayloadTree.vue +34 -1
  15. package/dist/vendored/components/CardGallery.vue +2 -0
  16. package/dist/vendored/components/CardSelect.vue +6 -0
  17. package/dist/vendored/components/ComponentPalette.vue +45 -38
  18. package/dist/vendored/components/ConfirmDialog.vue +20 -5
  19. package/dist/vendored/components/DebugPanel.vue +168 -127
  20. package/dist/vendored/components/EventEditor.vue +27 -3
  21. package/dist/vendored/components/JsonTree.vue +35 -4
  22. package/dist/vendored/components/LogValue.vue +2 -1
  23. package/dist/vendored/components/PropControl.vue +6 -2
  24. package/dist/vendored/components/StructureTree.vue +53 -2
  25. package/dist/vendored/components/setters/SetCode.vue +111 -3
  26. package/dist/vendored/styles/app.css +507 -132
  27. package/dist/vendored/styles/card-gallery.css +23 -2
  28. package/dist/vendored/styles/card-select.css +15 -0
  29. package/dist/vendored/styles/dropdown.css +3 -0
  30. package/dist/vendored/styles/json-tree.css +1 -1
  31. package/dist/vendored/styles/node-inspector.css +176 -119
  32. package/dist/vendored/styles/setters.css +91 -2
  33. package/dist/vendored/styles/structure-tree.css +158 -15
  34. package/package.json +1 -1
  35. package/dist/preview-editor/assets/index-BYB0hngG.js +0 -72
  36. package/dist/preview-editor/assets/index-CpBZEQDy.css +0 -1
@@ -3,8 +3,9 @@
3
3
  说明:设备模拟 UI(.dlg / .dtoast / .pk-* 等原生弹框白底)模拟真机外观,不随主题变化,保持固定。 */
4
4
  /* 配色 Token 与《深浅主题配色规范手册》映射(语义单一 / 双主题同义词切换):
5
5
  --accent/-2/-soft/-border/-hover = 主色 color-primary(及 hover/active 变体)
6
- --ok/-soft/-border/-strong = 成功 success(深色提亮 #34D399 / 浅色 #10B981)
7
- --warn/-soft/-border = 警告 warning(琥珀)
6
+ --ok/-soft/-border/-strong/-solid = 成功 success(深色提亮 #34D399 / 浅色 #10B981)
7
+ --on-ok = 成功实心填充(--ok-solid)上的文字
8
+ --warn/-soft/-border/-hover = 警告 warning(琥珀);--on-warn = 警告实心填充上的深色文字
8
9
  --danger/-soft/-hover = 错误 / 危险 error(红)
9
10
  --info/-soft/-border = 信息 info(与主色同源,均为蓝)
10
11
  --on-accent = 主色填充上的文字(深色 #0F1115 / 浅色 #fff)
@@ -38,10 +39,16 @@
38
39
  --warn: #FBBF24;
39
40
  --warn-soft: rgba(251, 191, 36, 0.14);
40
41
  --warn-border: rgba(251, 191, 36, 0.4);
42
+ --warn-hover: #F59E0B;
43
+ --on-warn: #0F1115;
41
44
  --ok: #34D399;
42
45
  --ok-soft: rgba(52, 211, 153, 0.16);
43
46
  --ok-border: rgba(52, 211, 153, 0.45);
44
47
  --ok-strong: #34D399;
48
+ /* 成功态「实心填充」徽标(标签 / 角标浮在任意底色上时用):--ok-solid 为底、--on-ok 为其上文字。
49
+ 与 --ok-soft(半透明,仅适合压在已知面板色上)区分:实心版不透明,浮在白色缩略图上仍达 WCAG AA。 */
50
+ --ok-solid: #17734A;
51
+ --on-ok: #ffffff;
45
52
  --info: #6B83F7;
46
53
  --info-soft: rgba(107, 131, 247, 0.14);
47
54
  --info-border: rgba(107, 131, 247, 0.45);
@@ -57,6 +64,9 @@
57
64
  --scrim: rgba(0, 0, 0, 0.55);
58
65
  --scrim-soft: rgba(0, 0, 0, 0.45);
59
66
  --scrim-faint: rgba(0, 0, 0, 0.4);
67
+ /* 模态模糊遮罩(深浅主题统一,不随主题翻转):确认框 / 网格预览 / 添加组件 / 远端预览 / 登录框共用 */
68
+ --scrim-modal: rgba(8, 10, 16, 0.55);
69
+ --scrim-modal-blur: 2px;
60
70
  /* 顶栏渐变、分隔条、分隔条抓手微光、白色叠加微光 */
61
71
  --bar-grad: linear-gradient(180deg, #171a20, #131519);
62
72
  --splitter: #5b6cff;
@@ -192,10 +202,14 @@
192
202
  --warn: #F59E0B;
193
203
  --warn-soft: rgba(245, 158, 11, 0.14);
194
204
  --warn-border: rgba(245, 158, 11, 0.4);
205
+ --warn-hover: #D97706;
206
+ --on-warn: #0F1115;
195
207
  --ok: #10B981;
196
208
  --ok-soft: rgba(16, 185, 129, 0.14);
197
209
  --ok-border: rgba(16, 185, 129, 0.4);
198
210
  --ok-strong: #166534;
211
+ --ok-solid: #166534;
212
+ --on-ok: #ffffff;
199
213
  --info: #4F6BF2;
200
214
  --info-soft: rgba(79, 107, 242, 0.12);
201
215
  --info-border: rgba(79, 107, 242, 0.4);
@@ -382,6 +396,12 @@ body {
382
396
  height: var(--ctrl-md);
383
397
  padding: 0 8px;
384
398
  }
399
+ /* 开关型图标按钮的「开启」态(如右侧接口调用面板开关):用主题色标示当前已展开 */
400
+ .app__btn--active {
401
+ background: var(--accent-soft);
402
+ color: var(--accent);
403
+ border-color: var(--accent-border);
404
+ }
385
405
  /* 顶栏图标按钮(刷新 / 连接)与远端、op-group 统一为 28px(--ctrl-sm),不再高 32px */
386
406
  .app__bar .app__btn--icon {
387
407
  height: var(--ctrl-sm);
@@ -423,11 +443,16 @@ body {
423
443
  .app__icon--chev {
424
444
  transition: transform 0.15s;
425
445
  }
426
- /* 下拉项:保存类 hover 蓝色、同步类 hover 绿色(基础布局见 dropdown.css .app__remote-item) */
446
+ /* 下拉项:保存/上传类 hover 蓝色与琥珀、同步类 hover 绿色(基础布局见 dropdown.css .app__remote-item) */
427
447
  .app__remote-item--save:hover {
428
448
  background: var(--accent-soft);
429
449
  color: var(--accent);
430
450
  }
451
+ /* 切图上传:琥珀色,与「版本推送」(蓝)、「同步」(绿)区分——传的是素材不是版本 */
452
+ .app__remote-item--upload:hover {
453
+ background: var(--warn-soft);
454
+ color: var(--warn);
455
+ }
431
456
  .app__remote-item--sync:hover {
432
457
  background: var(--ok-soft);
433
458
  color: var(--ok);
@@ -845,6 +870,37 @@ body {
845
870
  position: relative; /* 作为绝对定位 splitter 的定位上下文 */
846
871
  }
847
872
 
873
+ /* 中右工作区:纵向 flex——上为「调试面板 + 接口调用面板」两栏,下为贯穿两栏的共同状态栏。
874
+ 状态栏由 DebugPanel 内 Teleport 注入 .workside__bar;该目标在 DOM 中先于两栏容器
875
+ (Teleport 挂载要求目标已存在),故用 order 把它视觉置底。 */
876
+ .workside {
877
+ flex: 1 1 auto;
878
+ display: flex;
879
+ flex-direction: column;
880
+ min-width: 0;
881
+ min-height: 0;
882
+ }
883
+ .workside__bar {
884
+ flex: 0 0 auto;
885
+ order: 2;
886
+ }
887
+ /* 底部弹出面板容器(运行态 / 事件 / 绑定错误):Teleport 目标,宽度贯穿中右两栏;
888
+ 空容器(面板均 v-show 隐藏时)高度为 0,不占位 */
889
+ .workside__panels {
890
+ flex: 0 0 auto;
891
+ order: 1;
892
+ display: flex;
893
+ flex-direction: column;
894
+ }
895
+ .workside__cols {
896
+ flex: 1 1 auto;
897
+ display: flex;
898
+ min-width: 0;
899
+ min-height: 0;
900
+ /* 绝对定位 splitter 的定位上下文:分隔条只贯穿两栏区高度,不穿过底部面板 / 状态栏 */
901
+ position: relative;
902
+ }
903
+
848
904
  .phone {
849
905
  flex: 0 0 auto;
850
906
  display: flex;
@@ -877,21 +933,40 @@ body {
877
933
  flex-direction: column;
878
934
  }
879
935
 
880
- /* 拖拽分隔条:覆盖在预览列与调试面板的接缝上,绝对定位不占布局宽度 */
936
+ /* 拖拽分隔条:覆盖在接缝上,绝对定位不占布局宽度(命中宽 6px → 两侧各压 3px)。
937
+ 左条定位上下文为 .app__stage:预览列 | 工作区 的缝贯穿底面板 / 状态栏左缘,通到底部全程可拖;
938
+ 右条(.splitter--api)定位上下文为 .workside__cols:该缝在底面板区域不存在,只贯穿列区高度。 */
881
939
  .splitter {
882
940
  position: absolute;
883
941
  top: 0;
884
942
  bottom: 0;
885
- /* 以预览列右缘为接缝居中覆盖(宽 6px → 两侧各压 3px),不挤占实际宽度 */
886
943
  left: calc(var(--preview-width) - 3px);
887
944
  width: 6px;
888
945
  cursor: col-resize;
889
946
  z-index: var(--z-sticky);
890
947
  transition: background 0.15s ease;
891
948
  }
892
- .splitter:hover,
893
- .splitter.is-dragging {
949
+ /* 中右分隔条:以右侧「接口调用」面板右缘(即舞台右缘)回推面板宽度定位接缝 */
950
+ .splitter--api {
951
+ left: auto;
952
+ right: calc(var(--api-panel-width, 360px) - 3px);
953
+ }
954
+ /* 拖拽高亮统一规格:左 / 右竖向分隔条与底部面板头部横向拖拽条,hover / 拖拽中一律
955
+ 显示 2px 的 --splitter 高亮线(同色同粗细);竖条命中区仍为 6px,高亮只画居中 2px */
956
+ .splitter::after {
957
+ content: '';
958
+ position: absolute;
959
+ top: 0;
960
+ bottom: 0;
961
+ left: 1.5px;
962
+ width: 3px;
894
963
  background: var(--splitter);
964
+ opacity: 0;
965
+ transition: opacity 0.15s ease;
966
+ }
967
+ .splitter:hover::after,
968
+ .splitter.is-dragging::after {
969
+ opacity: 1;
895
970
  }
896
971
  /* 拖拽中:禁用文本选择,全局保持 col-resize 光标 */
897
972
  .phone--dragging,
@@ -1082,17 +1157,118 @@ body {
1082
1157
  flex: 1 1 auto;
1083
1158
  display: flex;
1084
1159
  flex-direction: column;
1085
- min-width: 300px;
1160
+ /* 中栏最小宽度:不得小于三分之一屏幕宽度(与中右分隔条 startApiDrag 的夹取一致) */
1161
+ min-width: 33.333vw;
1086
1162
  background: var(--bg-panel);
1087
1163
  border-left: 1px solid var(--border);
1088
1164
  }
1165
+
1166
+ /* 右侧常驻「接口调用」面板:默认 360px 宽,可经中右分隔条拖拽调节(最小 320px,
1167
+ 宽度由 App 以 --api-panel-width CSS 变量下发),与预览列 / 调试面板呈左中右布局。
1168
+ 展开/收起由顶栏按钮与面板内 ✕ 控制(v-if 整体挂载/卸载)。 */
1169
+ .apipanel {
1170
+ flex: 0 0 auto;
1171
+ width: var(--api-panel-width, 360px);
1172
+ min-width: 320px;
1173
+ display: flex;
1174
+ flex-direction: column;
1175
+ min-height: 0;
1176
+ background: var(--bg-panel);
1177
+ border-left: 1px solid var(--border);
1178
+ }
1179
+ .apipanel__head {
1180
+ flex: 0 0 auto;
1181
+ display: flex;
1182
+ align-items: center;
1183
+ gap: 8px;
1184
+ /* 与调试面板 tab 条同高(12px 上下 padding + 13px 字号 ≈ 42px),保证三条栏顶线对齐 */
1185
+ height: 40px;
1186
+ padding: 0 12px;
1187
+ border-bottom: 1px solid var(--border);
1188
+ }
1189
+ .apipanel__title {
1190
+ font-size: 13px;
1191
+ font-weight: 600;
1192
+ color: var(--text);
1193
+ white-space: nowrap;
1194
+ }
1195
+ .apipanel__spacer {
1196
+ flex: 1 1 auto;
1197
+ }
1198
+ .apipanel__btn {
1199
+ flex: 0 0 auto;
1200
+ display: inline-flex;
1201
+ align-items: center;
1202
+ justify-content: center;
1203
+ width: 28px;
1204
+ height: 28px;
1205
+ padding: 0;
1206
+ background: transparent;
1207
+ color: var(--text-dim);
1208
+ border: 1px solid transparent;
1209
+ border-radius: 8px;
1210
+ cursor: pointer;
1211
+ transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.05s;
1212
+ }
1213
+ .apipanel__btn:hover:not(:disabled) {
1214
+ background: var(--bg-hover);
1215
+ border-color: var(--border);
1216
+ color: var(--text);
1217
+ }
1218
+ .apipanel__btn:active:not(:disabled) {
1219
+ transform: translateY(1px);
1220
+ }
1221
+ .apipanel__btn:disabled {
1222
+ opacity: 0.5;
1223
+ cursor: default;
1224
+ }
1225
+ .apipanel__body {
1226
+ flex: 1 1 auto;
1227
+ overflow: auto;
1228
+ padding: 8px 12px;
1229
+ }
1230
+ /* 通用空状态占位(API 调用面板 / 卡片来源 tab 复用):徽章 + 图标 + 文案 + 弱提示,垂直居中 */
1231
+ .empty-state {
1232
+ display: flex;
1233
+ flex-direction: column;
1234
+ align-items: center;
1235
+ justify-content: center;
1236
+ gap: 12px;
1237
+ padding: 56px 16px;
1238
+ color: var(--text-faint);
1239
+ }
1240
+ /* 虚线圆形徽章:复用全局弱态配色(bg-hover 底 + 虚线描边),内嵌 20px 线性图标(插头/云等,随场景) */
1241
+ .empty-state__badge {
1242
+ display: inline-flex;
1243
+ align-items: center;
1244
+ justify-content: center;
1245
+ width: 48px;
1246
+ height: 48px;
1247
+ border-radius: 50%;
1248
+ background: var(--bg-hover);
1249
+ border: 1px dashed var(--border-strong);
1250
+ color: var(--text-faint);
1251
+ }
1252
+ .empty-state__badge svg {
1253
+ width: 20px;
1254
+ height: 20px;
1255
+ }
1256
+ .empty-state__hint {
1257
+ margin: 0;
1258
+ max-width: 240px;
1259
+ color: var(--text-faint);
1260
+ font-size: 11px;
1261
+ line-height: 1.6;
1262
+ text-align: center;
1263
+ }
1089
1264
  .debug__tabs {
1090
1265
  display: flex;
1091
1266
  border-bottom: 1px solid var(--border);
1092
1267
  }
1093
1268
  .debug__tab {
1094
1269
  flex: 1;
1095
- padding: 12px 8px;
1270
+ padding: 10px 8px;
1271
+ height: 39px;
1096
1272
  background: transparent;
1097
1273
  border: none;
1098
1274
  color: var(--text-dim);
@@ -1133,12 +1309,14 @@ body {
1133
1309
  position: relative;
1134
1310
  flex: 1 1 auto;
1135
1311
  overflow: auto;
1136
- padding: 12px 16px;
1312
+ /* padding: 12px 16px; */
1137
1313
  }
1138
- .debug__placeholder {
1139
- display: block;
1140
- width: 100%;
1141
- height: 38px;
1314
+ .debug__meta {
1315
+ margin: 0;
1316
+ padding: 8px 12px 0; /* 底部留白交给 hint 页脚,保证贴底无缝 */
1317
+ display: flex;
1318
+ flex-direction: column;
1319
+ min-height: 100%; /* 内容不足一屏时也能把 hint 推到面板底部 */
1142
1320
  }
1143
1321
  .debug__empty {
1144
1322
  color: var(--text-faint);
@@ -1184,8 +1362,12 @@ body {
1184
1362
  font-size: 12px;
1185
1363
  }
1186
1364
  .debug__meta-hint {
1187
- margin-top: 12px;
1188
- padding-top: 10px;
1365
+ /* 固定在面板底部:内容短时由 margin-top:auto 推底;内容超长滚动时 sticky 吸底不随列表滚走 */
1366
+ position: sticky;
1367
+ bottom: 0;
1368
+ margin: auto -12px 0;
1369
+ padding: 10px 12px;
1370
+ background: var(--bg-panel);
1189
1371
  border-top: 1px solid var(--border);
1190
1372
  color: var(--text-faint);
1191
1373
  font-size: 12px;
@@ -1198,14 +1380,14 @@ body {
1198
1380
  flex: 0 0 auto;
1199
1381
  display: flex;
1200
1382
  flex-direction: column;
1383
+ /* 顶缘拖拽条 .panelhead__edge 的定位上下文 */
1384
+ position: relative;
1201
1385
  /* 初始高度 240px;运行时由头部拖拽调整,并通过 JS 持久化回写 height */
1202
1386
  height: 240px;
1203
1387
  min-height: 120px;
1204
1388
  max-height: 60vh;
1205
1389
  /* hidden 避免面板自身出现滚动条(滚动交给 .statepanel__tree) */
1206
1390
  overflow: hidden;
1207
- /* 通过 flex order 把面板固定到状态栏之上,确保状态栏始终贴底(不被面板顶上来) */
1208
- order: 1;
1209
1391
  background: var(--bg-panel);
1210
1392
  border-top: 1px solid var(--border-strong);
1211
1393
  }
@@ -1216,13 +1398,37 @@ body {
1216
1398
  gap: 8px;
1217
1399
  height: var(--ctrl-lg);
1218
1400
  padding: 0 12px;
1219
- background: var(--bg-bar);
1220
1401
  border-bottom: 1px solid var(--border);
1221
1402
  font-size: 13px;
1222
1403
  color: var(--text);
1223
- /* 头部即拖拽手柄(无专门节点):整条可抓取,向上拖放大面板 */
1404
+ }
1405
+ /* 底面板顶缘拖拽条:与竖向分隔条同一规格——命中 6px、高亮 3px --splitter;
1406
+ 仅鼠标进入分割边缘才触发高亮 / 拖拽,头部本体不再响应(面板 overflow:hidden,
1407
+ 高亮线贴缝内侧 0~3px 绘制)。拖拽中经 is-dragging 保持高亮。 */
1408
+ .panelhead__edge {
1409
+ position: absolute;
1410
+ top: 0;
1411
+ left: 0;
1412
+ right: 0;
1413
+ height: 6px;
1224
1414
  cursor: row-resize;
1225
1415
  user-select: none;
1416
+ z-index: var(--z-sticky);
1417
+ }
1418
+ .panelhead__edge::after {
1419
+ content: '';
1420
+ position: absolute;
1421
+ left: 0;
1422
+ right: 0;
1423
+ top: 0;
1424
+ height: 3px;
1425
+ background: var(--splitter);
1426
+ opacity: 0;
1427
+ transition: opacity 0.15s ease;
1428
+ }
1429
+ .panelhead__edge:hover::after,
1430
+ .panelhead__edge.is-dragging::after {
1431
+ opacity: 1;
1226
1432
  }
1227
1433
  .statepanel__title {
1228
1434
  font-weight: 600;
@@ -1231,27 +1437,34 @@ body {
1231
1437
  .statepanel__title code {
1232
1438
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
1233
1439
  font-size: 12px;
1234
- color: var(--accent);
1440
+ /* 与 .debug__meta-row code 同一芯片语言:浅底 + 弱文字色,不用 accent 抢焦 */
1441
+ color: var(--text-dim);
1442
+ background: var(--bg-hover);
1443
+ padding: 1px 5px;
1444
+ border-radius: 4px;
1235
1445
  }
1236
1446
  .statepanel__close {
1237
1447
  margin-left: auto;
1238
1448
  display: inline-flex;
1239
1449
  align-items: center;
1240
1450
  justify-content: center;
1241
- width: 18px;
1242
- height: 18px;
1451
+ width: 24px;
1452
+ height: 24px;
1243
1453
  padding: 0;
1244
1454
  background: none;
1245
1455
  border: none;
1246
- color: var(--text-faint);
1247
- font-size: 15px;
1248
- line-height: 1;
1456
+ color: var(--text-dim);
1249
1457
  cursor: pointer;
1250
- transition: color 0.15s;
1458
+ border-radius: var(--radius-xs);
1459
+ transition: background 0.15s, color 0.15s;
1251
1460
  }
1252
1461
  .statepanel__close:hover {
1462
+ background: var(--bg-hover);
1253
1463
  color: var(--text);
1254
1464
  }
1465
+ .statepanel__close svg {
1466
+ display: block;
1467
+ }
1255
1468
  .statepanel__tree {
1256
1469
  flex: 1 1 auto;
1257
1470
  overflow: auto;
@@ -1282,63 +1495,72 @@ body {
1282
1495
  color: var(--danger);
1283
1496
  background: var(--danger-soft);
1284
1497
  }
1285
- /* 接口调用标签页工具条(仿 Chrome 控制台) */
1286
- .debug__clear {
1287
- /* 通用带边框按钮:固定在接口调用 tab 右上角、不随滚动,方便随时清空日志 */
1288
- position: sticky;
1289
- top: 0;
1290
- float: right;
1291
- z-index: var(--z-sticky);
1292
- display: inline-flex;
1293
- align-items: center;
1294
- justify-content: center;
1295
- width: 28px;
1296
- height: 28px;
1297
- padding: 0;
1298
- background: var(--bg-input);
1299
- color: var(--text);
1300
- border: 1px solid var(--border-strong);
1301
- border-radius: 8px;
1302
- cursor: pointer;
1303
- box-shadow: -10px 0 10px var(--bg-panel);
1304
- transition: background 0.15s, border-color 0.15s, transform 0.05s;
1305
- }
1306
- .debug__clear:hover:not(:disabled) {
1307
- background: var(--bg-hover);
1308
- border-color: var(--accent-border);
1309
- }
1310
- .debug__clear:active:not(:disabled) {
1311
- transform: translateY(1px);
1312
- }
1313
- .debug__clear:disabled {
1314
- opacity: 0.5;
1315
- cursor: default;
1316
- }
1317
- /* 接口调用列表顶部留白,避免首行被右上角浮动的清空按钮遮挡 */
1318
- .debug__list--api {
1319
- padding-top: 34px;
1320
- }
1321
1498
  .debug__list {
1322
1499
  list-style: none;
1323
1500
  margin: 0;
1324
1501
  padding: 0;
1325
1502
  }
1326
1503
  .debug__item {
1327
- padding: 4px 8px;
1504
+ padding: 9px 11px;
1328
1505
  margin-bottom: 6px;
1329
1506
  border-radius: 8px;
1330
1507
  font-size: 12px;
1331
1508
  line-height: 1.6;
1332
- word-break: break-all;
1509
+ /* break-all 会把键名/标识符拦腰拆行(msg → ms/g);anywhere 仅在单词真放不下时才断 */
1510
+ word-break: normal;
1511
+ overflow-wrap: anywhere;
1333
1512
  }
1334
1513
  .debug__item--err {
1335
- background: var(--danger-soft);
1514
+ display: grid;
1515
+ grid-template-columns: 52px 84px minmax(0, 1fr);
1516
+ align-items: baseline;
1517
+ gap: 8px;
1518
+ margin-bottom: 0;
1519
+ padding: 3px 12px 3px 10px;
1520
+ border-radius: 0;
1521
+ /* 左侧红条标示错误归属;行底透明避免整片红块,hover 才整行染 danger 色 */
1522
+ border-left: 2px solid var(--danger);
1523
+ border-bottom: 1px solid var(--border);
1524
+ background: transparent;
1336
1525
  color: var(--err-item-fg);
1526
+ font-size: 11px;
1527
+ line-height: 1.45;
1528
+ word-break: normal;
1529
+ }
1530
+ .debug__item--err:last-child {
1531
+ border-bottom: none;
1532
+ }
1533
+ .debug__item--err:hover {
1534
+ background: var(--danger-soft);
1535
+ }
1536
+ /* 错误类型列:等宽小标签,超长省略 */
1537
+ .debug__item--err .debug__kind {
1538
+ overflow: hidden;
1539
+ font-family: 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;
1540
+ font-size: 10px;
1541
+ color: var(--danger);
1542
+ text-overflow: ellipsis;
1543
+ white-space: nowrap;
1544
+ opacity: 1;
1545
+ }
1546
+ .err__msg {
1547
+ min-width: 0;
1548
+ word-break: break-word;
1337
1549
  }
1338
1550
  .debug__item--api {
1339
1551
  border: 1px solid var(--api-item-border);
1340
1552
  color: var(--api-item-fg);
1341
1553
  background: var(--api-item-bg);
1554
+ margin-bottom: 8px;
1555
+ }
1556
+ .debug__item--api:last-child {
1557
+ margin-bottom: 0;
1558
+ }
1559
+ /* 方法名与下方代码树同语言:等宽 + 显式行高(规范手册 6.2) */
1560
+ .debug__item--api .debug__kind {
1561
+ font-family: 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;
1562
+ font-size: 12px;
1563
+ line-height: 1.6;
1342
1564
  }
1343
1565
  .debug__kind {
1344
1566
  font-weight: 600;
@@ -1403,12 +1625,27 @@ body {
1403
1625
  .apt__branch,
1404
1626
  .apt__leaf {
1405
1627
  display: flex;
1406
- align-items: center;
1628
+ /* 值折行时键名/冒号保持首行对齐,center 会让它们悬在多行值的垂直中部 */
1629
+ align-items: baseline;
1407
1630
  gap: 4px;
1408
1631
  padding: 1px 4px;
1409
1632
  border-radius: 4px;
1410
1633
  cursor: pointer;
1411
1634
  }
1635
+ /* 冒号贴键(DevTools 风格):抵消与键之间的 flex gap,值仍保留 4px 间隔 */
1636
+ .apt .jt__colon {
1637
+ margin-left: -4px;
1638
+ }
1639
+ /* 键名不参与 flex 收缩:否则长值会把小 basis 的键列按比例挤到拦腰换行(msg → ms/g);
1640
+ 折行只应发生在值上(值已 min-width:0 + overflow-wrap:anywhere) */
1641
+ .apt .jt__key {
1642
+ flex-shrink: 0;
1643
+ }
1644
+ /* 值/摘要允许在剩余宽度内折行:解除 flex 项 min-content 下限 */
1645
+ .apt .jt__val,
1646
+ .apt .jt__preview {
1647
+ min-width: 0;
1648
+ }
1412
1649
  .apt__branch:hover,
1413
1650
  .apt__leaf:hover {
1414
1651
  background: var(--bg-hover);
@@ -1456,7 +1693,7 @@ body {
1456
1693
  /* right:0 让 JSON 树滚动条紧贴面板最右边(与其他 tab 用 body padding 作
1457
1694
  16px 滚动框不同,本 tab 滚动交给内部 .debug__scope-tree,需要贴边);
1458
1695
  left:16px 与 body 的 16px 内边距对齐,让树内容左缘与其他 tab 一致。 */
1459
- inset: 10px 10px 10px 16px;
1696
+ inset: 0;
1460
1697
  display: flex;
1461
1698
  flex-direction: column;
1462
1699
  min-height: 0;
@@ -1467,36 +1704,68 @@ body {
1467
1704
  overflow: auto;
1468
1705
  }
1469
1706
  .debug__scope-foot {
1470
- flex: 0 0 auto;
1471
1707
  position: absolute;
1472
- bottom: 0;
1473
- right: 0;
1708
+ bottom: 10px;
1709
+ right: 10px;
1474
1710
  display: flex;
1475
1711
  justify-content: flex-end;
1476
1712
  align-items: center;
1477
1713
  gap: 8px;
1478
- padding: 8px 12px;
1714
+ /* 悬浮操作条:卡片容器 + 投影,与滚动内容分层,不再“贴”在树内容上 */
1715
+ padding: 6px;
1716
+ background: var(--bg-bar);
1717
+ border: 1px solid var(--border);
1718
+ border-radius: 10px;
1719
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
1479
1720
  }
1480
1721
  .debug__copied {
1722
+ margin: 0 4px 0 8px;
1481
1723
  font-size: 12px;
1482
1724
  color: var(--accent);
1483
1725
  }
1726
+ /* 次级按钮:中性描边 + 弱文本色,hover 提亮 */
1484
1727
  .debug__copy {
1485
1728
  display: inline-flex;
1486
1729
  align-items: center;
1487
- height: var(--ctrl-sm);
1488
- padding: 0 14px;
1730
+ gap: 5px;
1731
+ height: 26px;
1732
+ padding: 0 10px;
1489
1733
  background: var(--bg-input);
1490
- color: var(--text);
1491
- border: 1px solid var(--accent-border);
1492
- border-radius: var(--radius-sm);
1493
- font-size: 13px;
1734
+ color: var(--text-dim);
1735
+ border: 1px solid var(--border-strong);
1736
+ border-radius: 7px;
1737
+ font-size: 12px;
1494
1738
  cursor: pointer;
1495
- transition: background 0.15s, border-color 0.15s;
1739
+ transition: background 0.15s, border-color 0.15s, color 0.15s;
1496
1740
  }
1497
1741
  .debug__copy:hover {
1498
1742
  background: var(--bg-hover);
1499
- border-color: var(--accent);
1743
+ border-color: var(--accent-border);
1744
+ color: var(--text);
1745
+ }
1746
+ .debug__copy-icn {
1747
+ flex: 0 0 auto;
1748
+ width: 13px;
1749
+ height: 13px;
1750
+ }
1751
+ /* 主按钮(应用):常态与其他边线按钮一致,hover 转绿色系(ok)提示“提交/生效”语义 */
1752
+ .debug__copy--primary:hover {
1753
+ background: var(--ok-soft);
1754
+ border-color: var(--ok-border);
1755
+ color: var(--ok);
1756
+ }
1757
+ /* 丢弃类次级按钮:hover 转 warn 色提示破坏性(重置丢弃内存编辑) */
1758
+ .debug__copy--warn:hover {
1759
+ background: var(--warn-soft);
1760
+ border-color: var(--warn-border);
1761
+ color: var(--warn);
1762
+ }
1763
+ /* 按钮分组间的竖向分隔线 */
1764
+ .debug__sep {
1765
+ width: 1px;
1766
+ height: 16px;
1767
+ margin: 0 2px;
1768
+ background: var(--border-strong);
1500
1769
  }
1501
1770
 
1502
1771
  /* 数据绑定 Raw 模式:直接复用 .debug__scope-wrap 的绝对定位盒(inset 已占满 body 内容区),
@@ -1521,8 +1790,8 @@ body {
1521
1790
  padding: 12px 14px;
1522
1791
  background: var(--bg-input);
1523
1792
  color: var(--text);
1524
- border: 1px solid var(--border-strong);
1525
- border-radius: 8px;
1793
+ /* border: 1px solid var(--border-strong); */
1794
+ /* border-radius: 8px; */
1526
1795
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1527
1796
  font-size: 12px;
1528
1797
  line-height: 1.6;
@@ -1531,9 +1800,9 @@ body {
1531
1800
  overflow: auto;
1532
1801
  outline: none;
1533
1802
  }
1534
- .debug__raw-editor:focus {
1803
+ /* .debug__raw-editor:focus {
1535
1804
  border-color: var(--accent-border);
1536
- }
1805
+ } */
1537
1806
  /* CodeJar 托管的原始 JSON 编辑器:Prism(json) 语法高亮配色(与 SetCode 暗色面板一致) */
1538
1807
  .debug__raw-editor .token.property,
1539
1808
  .debug__raw-editor .token.tag,
@@ -1639,12 +1908,12 @@ body {
1639
1908
  flex: 0 0 auto;
1640
1909
  display: flex;
1641
1910
  flex-direction: column;
1911
+ /* 顶缘拖拽条 .panelhead__edge 的定位上下文 */
1912
+ position: relative;
1642
1913
  height: 240px;
1643
1914
  min-height: 120px;
1644
1915
  max-height: 60vh;
1645
1916
  overflow: hidden;
1646
- /* 与运行态面板同属「状态栏之上的底部面板」,固定 order 确保状态栏始终贴底 */
1647
- order: 2;
1648
1917
  background: var(--bg-panel);
1649
1918
  border-top: 1px solid var(--border-strong);
1650
1919
  }
@@ -1655,10 +1924,6 @@ body {
1655
1924
  gap: 8px;
1656
1925
  height: var(--ctrl-lg);
1657
1926
  padding: 0 12px;
1658
- background: var(--bg-bar);
1659
- /* 头部即拖拽手柄(无专门节点):整条可抓取,向上拖放大面板 */
1660
- cursor: row-resize;
1661
- user-select: none;
1662
1927
  border-bottom: 1px solid var(--border);
1663
1928
  font-size: 13px;
1664
1929
  color: var(--text);
@@ -1679,18 +1944,23 @@ body {
1679
1944
  display: inline-flex;
1680
1945
  align-items: center;
1681
1946
  justify-content: center;
1682
- width: 20px;
1683
- height: 20px;
1947
+ width: 24px;
1948
+ height: 24px;
1684
1949
  padding: 0;
1685
1950
  background: none;
1686
1951
  border: none;
1687
- color: var(--text-faint);
1952
+ color: var(--text-dim);
1688
1953
  cursor: pointer;
1689
- transition: color 0.15s;
1954
+ border-radius: var(--radius-xs);
1955
+ transition: background 0.15s, color 0.15s;
1690
1956
  }
1691
1957
  .errpanel__iconbtn:hover:not(:disabled) {
1958
+ background: var(--bg-hover);
1692
1959
  color: var(--text);
1693
1960
  }
1961
+ .errpanel__iconbtn svg {
1962
+ display: block;
1963
+ }
1694
1964
  .errpanel__iconbtn:disabled {
1695
1965
  opacity: 0.35;
1696
1966
  cursor: not-allowed;
@@ -1699,33 +1969,100 @@ body {
1699
1969
  .errpanel__clear:hover:not(:disabled) {
1700
1970
  color: var(--danger);
1701
1971
  }
1972
+ /* 事件面板 tab 条:日志 / 错误 二选一,并入头部单行(标题之后、操作按钮之前)。
1973
+ 沿用 .debug__tabs 视觉语言(选中项 accent 短下划线,落到头部底发丝线上),
1974
+ 与头部同高,不再单独占一行面板高度。 */
1975
+ .errpanel__tabs {
1976
+ flex: 0 0 auto;
1977
+ align-self: stretch;
1978
+ display: flex;
1979
+ align-items: stretch;
1980
+ gap: 2px;
1981
+ margin-left: 4px;
1982
+ }
1983
+ .errpanel__tab {
1984
+ position: relative;
1985
+ display: inline-flex;
1986
+ align-items: center;
1987
+ gap: 5px;
1988
+ height: 100%;
1989
+ padding: 0 10px;
1990
+ background: none;
1991
+ border: none;
1992
+ color: var(--text-dim);
1993
+ font-size: 12px;
1994
+ cursor: pointer;
1995
+ transition: color 0.15s;
1996
+ }
1997
+ .errpanel__tab:hover {
1998
+ color: var(--text);
1999
+ }
2000
+ .errpanel__tab--active {
2001
+ color: var(--accent);
2002
+ }
2003
+ .errpanel__tab--active::after {
2004
+ content: '';
2005
+ position: absolute;
2006
+ left: 20%;
2007
+ right: 20%;
2008
+ bottom: -1px;
2009
+ height: 2px;
2010
+ background: var(--accent);
2011
+ }
2012
+ /* tab 计数小药丸:错误侧计数非 0 时转红,不切 tab 也能看出那边有货 */
2013
+ .errpanel__tab-count {
2014
+ min-width: 16px;
2015
+ padding: 0 5px;
2016
+ border-radius: 999px;
2017
+ background: var(--bg-hover);
2018
+ color: var(--text-faint);
2019
+ font-size: 11px;
2020
+ line-height: 15px;
2021
+ text-align: center;
2022
+ }
2023
+ .errpanel__tab--active .errpanel__tab-count {
2024
+ background: var(--accent-soft);
2025
+ color: var(--accent);
2026
+ }
2027
+ .errpanel__tab-count.is-hit,
2028
+ .errpanel__tab--active .errpanel__tab-count.is-hit {
2029
+ background: var(--danger-soft);
2030
+ color: var(--danger);
2031
+ }
1702
2032
  .errpanel__body {
1703
2033
  flex: 1 1 auto;
1704
2034
  overflow: auto;
1705
- padding: 12px 16px;
2035
+ /* 行贴边排布(行自带左右内边距),把竖向空间全部留给内容 */
2036
+ padding: 4px 0 6px;
1706
2037
  }
1707
- /* 事件面板内「日志 / 错误」分区标题 */
1708
- .ep__sec-title {
1709
- margin: 8px 0 6px;
1710
- padding-bottom: 4px;
1711
- font-size: 12px;
1712
- font-weight: 600;
1713
- color: var(--text-dim);
1714
- border-bottom: 1px dashed var(--border);
2038
+ /* 空态占位(复用 API 调用面板 .empty-state 语言):底部面板高度有限,
2039
+ 压缩留白与徽章尺寸,避免空态自身撑出滚动条 */
2040
+ .errpanel__body .empty-state {
2041
+ padding: 20px 16px;
2042
+ gap: 8px;
1715
2043
  }
1716
- .ep__sec-title:first-child {
1717
- margin-top: 0;
2044
+ .errpanel__body .empty-state__badge {
2045
+ width: 40px;
2046
+ height: 40px;
2047
+ }
2048
+ .errpanel__body .empty-state__badge svg {
2049
+ width: 18px;
2050
+ height: 18px;
1718
2051
  }
1719
- /* 事件面板日志:每行 = 等级标签 + 内容(语法高亮 / JSON 折叠) */
2052
+ .errpanel__body .empty-state__hint {
2053
+ max-width: 460px;
2054
+ }
2055
+ /* 事件面板日志:控制台风格高密度行 = 时间 | 等级 | 内容,发丝线分隔 */
1720
2056
  .debug__list--log {
1721
2057
  display: flex;
1722
2058
  flex-direction: column;
1723
2059
  }
1724
2060
  .log__item {
1725
- display: flex;
1726
- align-items: flex-start;
1727
- gap: 10px;
1728
- padding: 6px 8px;
2061
+ display: grid;
2062
+ grid-template-columns: 52px 44px minmax(0, 1fr);
2063
+ align-items: baseline;
2064
+ gap: 8px;
2065
+ padding: 2px 12px;
1729
2066
  border-bottom: 1px solid var(--border);
1730
2067
  }
1731
2068
  .log__item:last-child {
@@ -1734,31 +2071,40 @@ body {
1734
2071
  .log__item:hover {
1735
2072
  background: var(--bg-input);
1736
2073
  }
1737
- /* 等级标签:小药丸,按级别着色 */
2074
+ /* 行首时间戳:tabular-nums 保证整列对齐 */
2075
+ .log__time,
2076
+ .err__time {
2077
+ font-family: 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;
2078
+ font-size: 10px;
2079
+ font-variant-numeric: tabular-nums;
2080
+ color: var(--text-faint);
2081
+ }
2082
+ /* 等级标签:无边框小药丸,定宽成列对齐 */
1738
2083
  .log__tag {
1739
- flex: 0 0 auto;
1740
- margin-top: 1px;
1741
- padding: 1px 6px;
1742
- border-radius: 4px;
2084
+ justify-self: start;
2085
+ padding: 0 5px;
2086
+ border: none;
2087
+ border-radius: 3px;
1743
2088
  font-family: 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;
1744
- font-size: 11px;
2089
+ font-size: 10px;
1745
2090
  font-weight: 600;
1746
- line-height: 1.5;
2091
+ line-height: 14px;
1747
2092
  text-transform: uppercase;
1748
- letter-spacing: 0.4px;
2093
+ letter-spacing: 0.3px;
1749
2094
  color: var(--text-dim);
1750
- background: var(--bg-input);
1751
- border: 1px solid var(--border);
2095
+ background: var(--bg-hover);
2096
+ }
2097
+ .log__tag--info {
2098
+ color: var(--accent);
2099
+ background: var(--accent-soft);
1752
2100
  }
1753
2101
  .log__tag--warn {
1754
2102
  color: var(--log-warn-fg);
1755
2103
  background: var(--log-warn-bg);
1756
- border-color: var(--log-warn-border);
1757
2104
  }
1758
2105
  .log__tag--error {
1759
2106
  color: var(--danger);
1760
2107
  background: var(--danger-soft);
1761
- border-color: var(--danger-soft);
1762
2108
  }
1763
2109
  /* 内容区:基础类型内联、复合类型独占整行 */
1764
2110
  .log__content {
@@ -1767,10 +2113,10 @@ body {
1767
2113
  display: flex;
1768
2114
  flex-wrap: wrap;
1769
2115
  align-items: flex-start;
1770
- gap: 4px 10px;
2116
+ gap: 3px 8px;
1771
2117
  font-family: 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;
1772
- font-size: 12px;
1773
- line-height: 1.5;
2118
+ font-size: 11px;
2119
+ line-height: 1.45;
1774
2120
  color: var(--text);
1775
2121
  }
1776
2122
  .log__val {
@@ -1779,7 +2125,23 @@ body {
1779
2125
  }
1780
2126
  .log__json {
1781
2127
  flex: 1 1 100%;
1782
- padding: 2px 0;
2128
+ padding: 0;
2129
+ }
2130
+ /* 日志内嵌 JSON 树比接口面板再紧一档,去掉多余上下留白 */
2131
+ .log__json .apt {
2132
+ margin-top: 0;
2133
+ font-size: 11px;
2134
+ line-height: 1.4;
2135
+ }
2136
+ /* 根摘要行可点:hover 给底色提示;展开后明细列表缩进一级 */
2137
+ .log__json .apt__branch--root {
2138
+ cursor: pointer;
2139
+ border-radius: 4px;
2140
+ }
2141
+ .log__json .apt__list--nested {
2142
+ margin-left: 4px;
2143
+ padding-left: 14px;
2144
+ border-left: 1px solid var(--border);
1783
2145
  }
1784
2146
  .log__empty {
1785
2147
  color: var(--text-faint);
@@ -2196,8 +2558,8 @@ body {
2196
2558
  display: flex;
2197
2559
  align-items: center;
2198
2560
  justify-content: center;
2199
- background: rgba(8, 10, 16, 0.55);
2200
- backdrop-filter: blur(2px);
2561
+ background: var(--scrim-modal);
2562
+ backdrop-filter: blur(var(--scrim-modal-blur));
2201
2563
  }
2202
2564
  .rp-card {
2203
2565
  width: 300px;
@@ -2378,8 +2740,8 @@ body {
2378
2740
  display: flex;
2379
2741
  align-items: center;
2380
2742
  justify-content: center;
2381
- background: rgba(8, 10, 16, 0.55);
2382
- backdrop-filter: blur(2px);
2743
+ background: var(--scrim-modal);
2744
+ backdrop-filter: blur(var(--scrim-modal-blur));
2383
2745
  }
2384
2746
  .login-modal {
2385
2747
  width: 320px;
@@ -2478,8 +2840,8 @@ body {
2478
2840
  display: flex;
2479
2841
  align-items: center;
2480
2842
  justify-content: center;
2481
- background: rgba(8, 10, 16, 0.55);
2482
- backdrop-filter: blur(2px);
2843
+ background: var(--scrim-modal);
2844
+ backdrop-filter: blur(var(--scrim-modal-blur));
2483
2845
  }
2484
2846
  .confirm-modal {
2485
2847
  width: 360px;
@@ -2503,6 +2865,10 @@ body {
2503
2865
  .confirm-modal__title.is-danger {
2504
2866
  color: var(--danger);
2505
2867
  }
2868
+ /* 警告级(warn):覆盖推送类操作(版本推送等)——标题与图标取琥珀警告色,见配色规范 §2.7 / §3.4 */
2869
+ .confirm-modal__title.is-warn {
2870
+ color: var(--warn);
2871
+ }
2506
2872
  .confirm-modal__icon {
2507
2873
  width: 18px;
2508
2874
  height: 18px;
@@ -2555,6 +2921,15 @@ body {
2555
2921
  .confirm-modal__btn--danger:hover {
2556
2922
  background: var(--danger-hover);
2557
2923
  }
2924
+ /* 警告级确认按钮:琥珀实心 + 深色文字(琥珀底白字对比度不足,双主题统一深色 ink) */
2925
+ .confirm-modal__btn--warn {
2926
+ border-color: var(--warn);
2927
+ background: var(--warn);
2928
+ color: var(--on-warn);
2929
+ }
2930
+ .confirm-modal__btn--warn:hover {
2931
+ background: var(--warn-hover);
2932
+ }
2558
2933
  .confirm-fade-enter-active,
2559
2934
  .confirm-fade-leave-active {
2560
2935
  transition: opacity 0.15s ease;