@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.
- package/README.md +9 -0
- package/lib/client.js +41 -28
- 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+
|
|
31
|
-
//
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
403
|
-
//
|
|
404
|
-
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
style: {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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:
|
|
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),
|