@dougen/dsh-deepseek-usage 0.8.0 → 0.9.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 (3) hide show
  1. package/README.md +9 -0
  2. package/lib/client.js +41 -28
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -154,6 +154,15 @@ node lib/pricing-remote.js --check --html page.html --json
154
154
  > `node --test --test-isolation=none "test/*.test.mjs"`(Node ≥ 22.8),或逐个跑
155
155
  > `node test/parse.test.mjs`、`node test/pricing.test.mjs`、`node test/pricing-store.test.mjs`、
156
156
  > `node test/client-layout.test.mjs`、`node test/host-route.test.mjs`。
157
+ >
158
+ > 两种偶发失败都属于环境限制,不是插件行为,逐文件运行可稳定复现通过:
159
+ > - `host-route` 的"合并写回"用例依赖点击时的 `FORCED_GAP_MS`(30s)节流门;多个测试文件
160
+ > 共用同一进程(`--test-isolation=none`)时那条"强制同步"可能被门挡掉。
161
+ > - Windows 上原子写(写 `.tmp` 后 `rename`)可能被安全软件短暂占用而报
162
+ > `EPERM ... rename`;重跑即过。
163
+ >
164
+ > 另:`test/host-route.test.mjs` 与 `test/pricing-store.test.mjs` 都只需要一个可写的临时目录
165
+ > (`os.tmpdir()`),若该目录不可写(`mkdtemp ... EPERM`),把 `TEMP`/`TMP` 指到任意可写目录即可。
157
166
 
158
167
  ## Uninstall / 卸载
159
168
 
package/lib/client.js CHANGED
@@ -27,9 +27,11 @@ window.__ModuleLoader__.load({
27
27
  // ---- constants -------------------------------------------------
28
28
  const POLL_MS = 5 * 60 * 1000;
29
29
  const USAGE_PATH = "/api/deepseek-usage";
30
- // 常态卡片高度:上下 padding 8+8 + 余额行 lineHeight 28 + 边框 2 = 46。
31
- // 异常态把卡片置空时用它兜住高度,侧边栏高度不跳动。
32
- const CARD_MIN_HEIGHT = 46;
30
+ // 常态卡片高度:上下 padding 8+16 + 金额行 minHeight 28 + 边框 2 = 54。
31
+ // 底部多留的 8px 是为了让倒计时那一行与下方单价行之间有呼吸感。
32
+ // 倒计时与圆点都在金额行内定位,不额外增高(无头 Chromium 实测 cardH=54)。
33
+ // 异常态把卡片置空时用它兜住同一个高度,侧边栏高度不跳动。
34
+ const CARD_MIN_HEIGHT = 54;
33
35
  // 卡片还没拿到余额时的快速重试节奏(宿主刚重启、接口刚起来、或本次请求失败):
34
36
  // 否则要等满 5 分钟轮询才会从空卡片变成真实数字。
35
37
  const QUICK_RETRY_MS = [4000, 8000, 15000, 30000];
@@ -382,7 +384,9 @@ window.__ModuleLoader__.load({
382
384
  boxSizing: "border-box",
383
385
  flex: "1 1 100%",
384
386
  minWidth: 0,
385
- padding: "8px 10px",
387
+ // 上 8 下 10(配合单价行 bottom:2,这组是用户看过后选定的观感)。
388
+ // 顶部保持 8px 不动,圆点才能继续紧贴右上角。
389
+ padding: "8px 10px 12px",
386
390
  borderRadius: 10,
387
391
  border: "1px solid " + C.border,
388
392
  background: C.bg,
@@ -399,35 +403,44 @@ window.__ModuleLoader__.load({
399
403
  },
400
404
  onClick: onCardClick,
401
405
  },
402
- // 第一行:余额(24px,符号与数字 3px 间距)。右侧留出"圆点 + 倒计时"的位置:
403
- // 倒计时贴右,圆点再靠右,所以余额右侧 padding 是 100(约 3 个倒计时字符宽)。
404
- h("div", { style: { display: "flex", alignItems: "baseline", minWidth: 0, paddingRight: 100, gap: 6 } },
406
+ // 金额行:余额 + 右侧「倒计时 + 峰谷圆点」。
407
+ // 倒计时与圆点放在同一个 flex 行里、alignItems:center,两者圆心必然重合;
408
+ // 整组 alignSelf:flex-start + 负 margin,让圆点距卡片顶/右各 8px。
409
+ // 两个反面做法都试过并实测过:
410
+ // · alignSelf:center → 圆点被压到卡片中线,不再是"右上角";
411
+ // · paddingTop:6 → 金额行被撑高,卡片被撑大,圆点反而更靠下。
412
+ // 倒计时 minWidth:0 + overflow:hidden:窄侧边栏下先省略号截断,不挤压余额
413
+ // (实测 "2d 23h" 在 170px 宽的卡片里仍放得下)。
414
+ h("div", { style: { display: "flex", alignItems: "baseline", minHeight: 28, minWidth: 0, gap: 6 } },
405
415
  h("span", { style: { fontWeight: 700, fontSize: 24, color: C.label, lineHeight: "28px", marginRight: 3 } }, symbol),
406
- h("span", { style: { fontWeight: 700, fontSize: 24, color: C.label, lineHeight: "28px" } }, money(balance && balance.total))),
407
- // 倒计时:距下次峰谷切换的剩余时间(`2d 15h` / `5h 47m` / `23m` / `switching`)。
408
- // 与圆点同一行、位于圆点左侧;英文单位且无前缀,中英界面一致。
409
- h("span", {
410
- style: {
411
- position: "absolute",
412
- top: 9,
413
- right: 27,
414
- left: 9,
415
- textAlign: "right",
416
- fontSize: 12,
417
- lineHeight: "14px",
418
- color: C.sub,
419
- overflow: "hidden",
420
- textOverflow: "ellipsis",
421
- whiteSpace: "nowrap",
422
- },
423
- }, countdown),
424
- // 峰谷指示灯:只有颜色(橙=高峰 / 绿=空闲),没有 title、没有其他文字。
425
- h("span", { style: { position: "absolute", top: 8, right: 9, ...dot } }),
416
+ h("span", { style: { fontWeight: 700, fontSize: 24, color: C.label, lineHeight: "28px" } }, money(balance && balance.total)),
417
+ // 负 margin 只挪动整组,不改变金额行高度(卡片高度由内边距决定)。
418
+ // 实测:marginTop -4 与 marginRight -3 时,圆点距卡片顶、右各 8px
419
+ // (右侧不能按"内边距 10 − 8"去推,内边距本就含在行宽里)。
420
+ h("span", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0, marginLeft: "auto", flex: "0 1 auto", alignSelf: "flex-start", marginTop: -4, marginRight: -3 } },
421
+ // 倒计时:距下次峰谷切换的剩余时间(`2d 15h` / `5h 47m` / `23m` / `switching`)。
422
+ // 纯英文单位、无前缀,中英界面一致。
423
+ // 字号/字重刻意与右下角单价数字对齐(继承卡片正文 12px、fontWeight 600),
424
+ // 让右上角这行和右下角单价行是同一套文字样式。
425
+ h("span", {
426
+ style: {
427
+ fontWeight: 600,
428
+ color: C.sub,
429
+ minWidth: 0,
430
+ overflow: "hidden",
431
+ textOverflow: "ellipsis",
432
+ whiteSpace: "nowrap",
433
+ },
434
+ }, countdown),
435
+ // 峰谷指示灯:只有颜色(橙=高峰 / 绿=空闲),没有 title、没有其他文字。
436
+ h("span", { style: dot }))),
426
437
  // 底部行:只剩当前档单价,恒靠右下角。
438
+ // 这组 bottom:2 + 卡片下内边距 10 是用户看过多组对比后选定的观感(价格略微下移、
439
+ // 下方不再空一大块)。注意绝对定位的行不参与卡片高度计算,改内边距时两者要一起看。
427
440
  // 用 flex-end 而不是 space-between:容器只有一个子元素时 space-between 会把它
428
441
  // 推到最左侧(0.6.0 的回归点)。
429
442
  h("span", {
430
- style: { position: "absolute", left: 9, right: 9, bottom: 4, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 6 },
443
+ style: { position: "absolute", left: 9, right: 9, bottom: 2, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 6 },
431
444
  },
432
445
  h("span", { style: { display: "inline-flex", alignItems: "center", gap: 5, flex: "none" } },
433
446
  Price(h(IconIn, null), t("price.input"), tier && tier.input),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dougen/dsh-deepseek-usage",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "DeepSeek 余额侧边栏插件:余额(官方 API)、当前档单价与峰谷时段指示灯,支持中/英文界面。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",