@loommii/dsh-provider-usage 0.10.0 → 0.11.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 +3 -2
- package/docs/CHANGELOG.md +18 -1
- package/lib/client.js +195 -19
- package/lib/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-provider-usage — DSH「用量中心」
|
|
2
2
|
|
|
3
|
-
> 当前版本 **v0.
|
|
3
|
+
> 当前版本 **v0.11.0** · npm `@loommii/dsh-provider-usage` · [更新历史](docs/CHANGELOG.md)
|
|
4
4
|
|
|
5
5
|
DSH Web GUI 插件 **「用量中心」**:一个常驻右下角的用量卡片,实时显示你的 AI 服务用量 / 余额,不用再打开网页查;附带本地 Token 统计页,不联网也能看自己今天用了多少。
|
|
6
6
|
|
|
@@ -85,7 +85,8 @@ dsh plugin --profile web remove @loommii/dsh-provider-usage
|
|
|
85
85
|
新添加的提供方默认启用。暂停后该实例**不再轮询查询**(卡片 30s 自动刷新跳过它),
|
|
86
86
|
卡片切换菜单里也**不可选**;暂停的若是当前卡片实例会自动切到其他启用实例,全部暂停时卡片隐藏。
|
|
87
87
|
启用/暂停只影响查询与卡片选择,编辑 / 删除 / Key 配置都原样保留
|
|
88
|
-
-
|
|
88
|
+
- 设置页有三个标签:「提供方」管理实例,「用量统计」查看本地 Token 统计,「卡片设置」自定义卡片显示
|
|
89
|
+
- **卡片设置**:可分别开关卡片上的信息模块(主数字 / 副行信息 / 窗口进度条 / 状态 chip / 提供方名称),也可整体「显示卡片」开关隐藏整卡;隐藏后不再轮询查询。全部模块关闭时卡片视为隐藏,并提供「恢复默认」一键还原
|
|
89
90
|
- 设置保存在本机浏览器中;删掉实例不会上传或泄露任何 Key
|
|
90
91
|
- 卡片拖动后的位置会自动保存,下次打开还是老位置
|
|
91
92
|
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## v0.
|
|
3
|
+
## v0.11.0(未发布)
|
|
4
|
+
|
|
5
|
+
### 新功能:卡片设置(用量中心第三页)
|
|
6
|
+
|
|
7
|
+
- **新增「卡片设置」页**(用量中心二级菜单变为「提供方 / 用量统计 / 卡片设置」三页):
|
|
8
|
+
5 个开关分别控制卡片信息模块——主数字、副行信息、窗口进度条、状态 chip、提供方名称;
|
|
9
|
+
另有「显示卡片」总开关隐藏整卡;改动即时生效并持久化到 localStorage
|
|
10
|
+
- **隐藏即停轮询**:`visible=false` 或全部信息模块关闭时卡片完全隐藏(不再渲染空壳),
|
|
11
|
+
30s 自动刷新与查询请求随之停止,重新显示后立即恢复
|
|
12
|
+
- **持久化健壮性**:设置版本升 v6,v3~v5 旧配置自动迁移;card 子项逐项布尔归一化,
|
|
13
|
+
脏数据/非布尔值回落默认(杜绝开关显示与实际渲染分裂);新增跨页签 `storage` 同步,
|
|
14
|
+
避免多页签 last-write-wins 覆盖丢配置;localStorage 写入失败时设置页内联提示(4s 自动消失)
|
|
15
|
+
- **恢复默认**:卡片设置页新增两段式确认「恢复默认」按钮,一键还原全部开关并重新显示卡片
|
|
16
|
+
- **全关空态引导**:所有模块关闭时,设置页提供方/卡片设置页显示「卡片已隐藏」提示
|
|
17
|
+
- **可访问性修正**:设置开关行由 `label` 包裹 `button` 改为语义化 `div + role="switch"` 结构
|
|
18
|
+
- README 使用说明同步更新(两个标签 → 三个标签,补充卡片设置说明)
|
|
19
|
+
|
|
20
|
+
## v0.10.0(2026-09-09)
|
|
4
21
|
|
|
5
22
|
- **新增提供方 AMD Radeon Cloud (中国)(余额+配额卡)**:实测端点 `GET {baseUrl}/usage`(`https://developer.amd.com.cn/radeon/api/v1/usage`,Bearer API Key)——今日剩余 pts 为主数字(3 位小数向下取整百分比)、副行已用/限额 + 剩余(pts)、单日窗口进度条 + 重置倒计时;透传今日/近24h/近30天/累计时间段汇总与按模型拆分(`by_model`)、单次调用明细(`recent`)
|
|
6
23
|
- **无周/月窗口**:AMD 只按日限额计(`daily_cost_limit/used/remaining_usd`),接口无 weekly/monthly 字段;适配器只画「今日」一行进度条
|
package/lib/client.js
CHANGED
|
@@ -20,7 +20,37 @@ window.__ModuleLoader__.load({
|
|
|
20
20
|
|
|
21
21
|
const inject = ['slots'];
|
|
22
22
|
const SETTINGS_KEY = 'dsh-provider-usage.settings';
|
|
23
|
-
const
|
|
23
|
+
const SETTINGS_VERSION = 6;
|
|
24
|
+
// 卡片信息模块显示开关:单一数据源(渲染门控、设置面板、迁移归一化共用)。
|
|
25
|
+
// 默认全开;新增模块只需在此加一项并同步 zh 文案。
|
|
26
|
+
const CARD_MODULES = [
|
|
27
|
+
{ key: 'showMainNumber', default: true },
|
|
28
|
+
{ key: 'showSubRow', default: true },
|
|
29
|
+
{ key: 'showWindowBars', default: true },
|
|
30
|
+
{ key: 'showChip', default: true },
|
|
31
|
+
{ key: 'showProviderName', default: true },
|
|
32
|
+
];
|
|
33
|
+
function defaultCard() {
|
|
34
|
+
var out = {};
|
|
35
|
+
for (var i = 0; i < CARD_MODULES.length; i++) out[CARD_MODULES[i].key] = CARD_MODULES[i].default;
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
function normalizeCard(raw) {
|
|
39
|
+
var out = defaultCard();
|
|
40
|
+
if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
|
|
41
|
+
for (var i = 0; i < CARD_MODULES.length; i++) {
|
|
42
|
+
var k = CARD_MODULES[i].key;
|
|
43
|
+
if (typeof raw[k] === 'boolean') out[k] = raw[k];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
function cardModuleOn(card, key) {
|
|
49
|
+
return (card && card[key]) !== false;
|
|
50
|
+
}
|
|
51
|
+
const DEFAULT_SETTINGS = { visible: true, refreshMs: 30000, providerId: 'opencode-go', right: 16, bottom: 16, settingsVersion: SETTINGS_VERSION,
|
|
52
|
+
card: defaultCard(),
|
|
53
|
+
};
|
|
24
54
|
// 卡片常驻 body 顶层(z-index 与 dsh-pet 同值,≈int32 上限)
|
|
25
55
|
const Z_INDEX = 2147483000;
|
|
26
56
|
// 适配器元数据(与 host ADAPTERS 对应;logo 与显示名用于设置页/菜单)
|
|
@@ -73,6 +103,27 @@ window.__ModuleLoader__.load({
|
|
|
73
103
|
used: '已用',
|
|
74
104
|
errorTitle: '无法获取用量',
|
|
75
105
|
nav: '用量中心',
|
|
106
|
+
// 卡片设置页
|
|
107
|
+
cardSettings: '卡片设置',
|
|
108
|
+
cardSettingsDesc: '自定义卡片上显示的信息模块。',
|
|
109
|
+
showCard: '显示卡片',
|
|
110
|
+
showCardHint: '关闭后卡片完全隐藏(设置页仍可正常管理提供方与用量统计)。',
|
|
111
|
+
showMainNumber: '主数字',
|
|
112
|
+
showMainNumberHint: '卡片核心数值(剩余额度或剩余百分比)。',
|
|
113
|
+
showSubRow: '副行信息',
|
|
114
|
+
showSubRowHint: '已用/总额 + 剩余额度(Command Code / AMD 等百分比卡)。',
|
|
115
|
+
showWindowBars: '窗口进度条',
|
|
116
|
+
showWindowBarsHint: '5小时滚动/7天/每月(或 AMD 今日)用量进度条。',
|
|
117
|
+
showChip: '状态 chip',
|
|
118
|
+
showChipHint: '卡片右上角状态标签(正常/查询中/未更新/注意)。',
|
|
119
|
+
showProviderName: '提供方名称',
|
|
120
|
+
showProviderNameHint: '卡片头部提供方名称与切换菜单。',
|
|
121
|
+
allModulesOff: '所有信息模块已关闭,卡片已隐藏(可在这里重新开启)。',
|
|
122
|
+
saveFailed: '设置保存失败:浏览器本地存储不可用,本次修改刷新后将丢失。',
|
|
123
|
+
resetCard: '恢复默认',
|
|
124
|
+
resetCardConfirm: '再次点击确认恢复默认',
|
|
125
|
+
// 用量中心副标题(随标签数量变化)
|
|
126
|
+
navDesc: '管理提供方、查看本地用量统计,并自定义卡片显示。',
|
|
76
127
|
};
|
|
77
128
|
|
|
78
129
|
var styleId = 'dsh-provider-usage/styles.css';
|
|
@@ -108,7 +159,7 @@ window.__ModuleLoader__.load({
|
|
|
108
159
|
'.dsh-pu-menu-item.active{background:rgba(255,179,198,.14);color:#FFB3C6}',
|
|
109
160
|
'.dsh-pu-menu-item .mini-logo{width:22px;height:22px;border-radius:6px;flex:none;display:flex;align-items:center;justify-content:center;overflow:hidden}',
|
|
110
161
|
'.dsh-pu-menu-item .check{margin-left:auto;color:#FFB3C6;font-size:12px}',
|
|
111
|
-
'.dsh-pu-card-title{font-size:14px;font-weight:600;color:#EFE0E5;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
|
|
162
|
+
'.dsh-pu-card-title{font-size:14px;font-weight:600;color:#EFE0E5;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}',
|
|
112
163
|
'.dsh-pu-chip{display:inline-flex;align-items:center;gap:5px;border-radius:999px;padding:2px 8px;font-size:10px;font-weight:600;flex:none}',
|
|
113
164
|
'.dsh-pu-chip.ok{background:rgba(102,187,106,.14);color:#7ED68A}',
|
|
114
165
|
'.dsh-pu-chip.warn{background:rgba(255,167,38,.15);color:#FFC46B}',
|
|
@@ -150,6 +201,10 @@ window.__ModuleLoader__.load({
|
|
|
150
201
|
'.zGbnIq_rowNameDim{color:var(--dsw-alias-label-tertiary)}',
|
|
151
202
|
'.zGbnIq_rowCard .zGbnIq_credentialDot.dsh-pu-dot-paused{background:var(--dsw-alias-label-tertiary,#8b93a7)}',
|
|
152
203
|
'.zGbnIq_rowPaused .zGbnIq_rowIdentity .zGbnIq_rowName{color:var(--dsw-alias-label-tertiary)}',
|
|
204
|
+
// ── 卡片设置页:开关行文本弹性(label 语义、flex 排布见 CardSettingsPanel)──
|
|
205
|
+
'.dsh-pu-switchRowText{flex-direction:column;gap:2px;min-width:0;flex:1;display:flex}',
|
|
206
|
+
'.dsh-pu-switchRowText .zGbnIq_advancedHint{margin:0}',
|
|
207
|
+
'.dsh-pu-cardEmpty{border:1px dashed var(--dsw-alias-border-l3);border-radius:10px;margin:2px 0 10px;padding:8px 10px;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}',
|
|
153
208
|
].join('');
|
|
154
209
|
var tag = document.createElement('style');
|
|
155
210
|
tag.dataset.plugin = 'dsh-provider-usage';
|
|
@@ -163,10 +218,11 @@ window.__ModuleLoader__.load({
|
|
|
163
218
|
try {
|
|
164
219
|
var s = JSON.parse(window.localStorage.getItem(SETTINGS_KEY) || 'null');
|
|
165
220
|
if (s && typeof s === 'object' &&
|
|
166
|
-
(s.settingsVersion ===
|
|
167
|
-
//
|
|
221
|
+
(s.settingsVersion === SETTINGS_VERSION || s.settingsVersion === 3 || s.settingsVersion === 4 || s.settingsVersion === 5)) {
|
|
222
|
+
// v5→v6 新增 card 显示开关(默认全开;仅布尔值生效),其余偏好保留
|
|
168
223
|
return Object.assign({}, DEFAULT_SETTINGS, s, {
|
|
169
224
|
providerId: typeof s.providerId === 'string' ? s.providerId : DEFAULT_SETTINGS.providerId,
|
|
225
|
+
card: normalizeCard(s.card),
|
|
170
226
|
});
|
|
171
227
|
}
|
|
172
228
|
// 设置结构升级:v2→v3 移除用户可配置的 zIndex(固定与 dsh-pet 一致),其余偏好保留
|
|
@@ -181,14 +237,21 @@ window.__ModuleLoader__.load({
|
|
|
181
237
|
}
|
|
182
238
|
var settingsState = loadSettings();
|
|
183
239
|
var settingsListeners = new Set();
|
|
240
|
+
// 保存失败时通知(先广播 onPersistFailed,再广播常规刷新):
|
|
241
|
+
// 订阅者根据回调结果展示“无法保存”提示;卡片渲染不依赖持久化结果,避免闪烁。
|
|
184
242
|
function saveSettings() {
|
|
185
|
-
|
|
243
|
+
var ok = true;
|
|
244
|
+
try { window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(settingsState)); }
|
|
245
|
+
catch (e) { ok = false; }
|
|
246
|
+
return ok;
|
|
186
247
|
}
|
|
187
248
|
function getSettings() { return settingsState; }
|
|
188
249
|
function setSettings(patch) {
|
|
189
|
-
settingsState = Object.assign({}, settingsState, patch);
|
|
190
|
-
saveSettings();
|
|
191
|
-
settingsListeners.forEach(function (fn) {
|
|
250
|
+
settingsState = Object.assign({}, settingsState, typeof patch === 'function' ? patch(settingsState) : patch);
|
|
251
|
+
var ok = saveSettings();
|
|
252
|
+
settingsListeners.forEach(function (fn) {
|
|
253
|
+
try { fn(ok ? null : new Error('settings persist failed')); } catch (e) { /* ignore */ }
|
|
254
|
+
});
|
|
192
255
|
}
|
|
193
256
|
function subscribeSettings(fn) {
|
|
194
257
|
settingsListeners.add(fn);
|
|
@@ -199,6 +262,16 @@ window.__ModuleLoader__.load({
|
|
|
199
262
|
useEffect(function () { return subscribeSettings(function () { setS(getSettings()); }); }, []);
|
|
200
263
|
return s;
|
|
201
264
|
}
|
|
265
|
+
// 跨页签同步:其它页签写入后重读并广播(消除 last-write-wins 覆盖丢配置)
|
|
266
|
+
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
267
|
+
window.addEventListener('storage', function (e) {
|
|
268
|
+
if (e.key !== SETTINGS_KEY) return;
|
|
269
|
+
settingsState = loadSettings();
|
|
270
|
+
settingsListeners.forEach(function (fn) {
|
|
271
|
+
try { fn(null); } catch (err) { /* ignore */ }
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
}
|
|
202
275
|
|
|
203
276
|
// ── 供应商实例清单(v0.8.0:host 端 providers.json 为单一事实源,localStorage 只是写穿透缓存)──
|
|
204
277
|
// 修复「重启后提供方清单被静默重建」:此前清单只存 localStorage,存储 key 一旦丢失
|
|
@@ -347,6 +420,9 @@ window.__ModuleLoader__.load({
|
|
|
347
420
|
// ── 用量卡片(布局借鉴 Rainytoken 小组件卡片,常驻右下角)──────────
|
|
348
421
|
function UsageCard() {
|
|
349
422
|
var s = useSettings();
|
|
423
|
+
var card = s.card || {};
|
|
424
|
+
function cardOn(key) { return cardModuleOn(card, key); }
|
|
425
|
+
var allModulesOff = !cardOn('showMainNumber') && !cardOn('showSubRow') && !cardOn('showWindowBars') && !cardOn('showChip') && !cardOn('showProviderName');
|
|
350
426
|
var providers = useProviders();
|
|
351
427
|
var [data, setData] = useState(null);
|
|
352
428
|
var [loading, setLoading] = useState(false);
|
|
@@ -432,11 +508,14 @@ window.__ModuleLoader__.load({
|
|
|
432
508
|
.finally(function () { setLoading(false); });
|
|
433
509
|
}, [curKey]);
|
|
434
510
|
|
|
511
|
+
// 仅在卡片实际可见时轮询:s.visible=false 或全部模块关闭(空壳隐藏)时不发起请求
|
|
512
|
+
var pollActive = s.visible && !allModulesOff;
|
|
435
513
|
useEffect(function () {
|
|
514
|
+
if (!pollActive) return undefined;
|
|
436
515
|
load();
|
|
437
516
|
var timer = window.setInterval(load, s.refreshMs || 30000);
|
|
438
517
|
return function () { window.clearInterval(timer); };
|
|
439
|
-
}, [load, s.refreshMs]);
|
|
518
|
+
}, [load, pollActive, s.refreshMs]);
|
|
440
519
|
|
|
441
520
|
// 点击卡片外部关闭菜单
|
|
442
521
|
useEffect(function () {
|
|
@@ -449,7 +528,7 @@ window.__ModuleLoader__.load({
|
|
|
449
528
|
return function () { document.removeEventListener('mousedown', onDoc); };
|
|
450
529
|
}, [menuOpen]);
|
|
451
530
|
|
|
452
|
-
if (!s.visible || !current) return null;
|
|
531
|
+
if (!s.visible || allModulesOff || !current) return null;
|
|
453
532
|
|
|
454
533
|
// 状态语义:请求中=呼吸绿“查询中”(优先于旧数据状态);正常/注意(stale 或余额不足)/错误
|
|
455
534
|
var loadingCls = loading ? ' dsh-pu-chip-loading' : '';
|
|
@@ -528,12 +607,12 @@ window.__ModuleLoader__.load({
|
|
|
528
607
|
// 窗口行/主值/警告条已覆盖全部信息,extra 全文不再展示(保持卡片干净)
|
|
529
608
|
var extra = null;
|
|
530
609
|
body = React.createElement('div', null,
|
|
531
|
-
React.createElement('div', { className: 'dsh-pu-remain' },
|
|
610
|
+
cardOn('showMainNumber') ? React.createElement('div', { className: 'dsh-pu-remain' },
|
|
532
611
|
React.createElement('span', { className: 'dsh-pu-remain-big' }, (isCommandCode || isAmd) ? (remainPct === null ? '--' : remainPct.toFixed(3) + '%') : main),
|
|
533
|
-
React.createElement('span', { className: 'dsh-pu-remain-label' }, (isCommandCode || isAmd) ? ' ' + zh.remaining + '(' + (isAmd ? zh.daily : zh.monthly) + ')' : ' ' + mainLabel)),
|
|
612
|
+
React.createElement('span', { className: 'dsh-pu-remain-label' }, (isCommandCode || isAmd) ? ' ' + zh.remaining + '(' + (isAmd ? zh.daily : zh.monthly) + ')' : ' ' + mainLabel)) : null,
|
|
534
613
|
warn,
|
|
535
|
-
cc,
|
|
536
|
-
winRows,
|
|
614
|
+
cardOn('showSubRow') ? cc : null,
|
|
615
|
+
cardOn('showWindowBars') ? winRows : null,
|
|
537
616
|
extra);
|
|
538
617
|
}
|
|
539
618
|
|
|
@@ -571,9 +650,9 @@ window.__ModuleLoader__.load({
|
|
|
571
650
|
onClick: function (e) { if (draggedRef.current) { draggedRef.current = false; return; } e.stopPropagation(); if (multiple) setMenuOpen(!menuOpen); },
|
|
572
651
|
},
|
|
573
652
|
React.createElement('span', { className: 'dsh-pu-logo ' + logoClass }, logoEl),
|
|
574
|
-
React.createElement('span', { className: 'dsh-pu-card-title' }, title),
|
|
653
|
+
cardOn('showProviderName') ? React.createElement('span', { className: 'dsh-pu-card-title' }, title) : null,
|
|
575
654
|
multiple ? React.createElement('span', { className: 'caret' }, menuOpen ? '▴' : '▾') : null),
|
|
576
|
-
React.createElement('span', { className: 'dsh-pu-chip ' + level + loadingCls }, React.createElement('i', null), chipText)),
|
|
655
|
+
cardOn('showChip') ? React.createElement('span', { className: 'dsh-pu-chip ' + level + loadingCls }, React.createElement('i', null), chipText) : null),
|
|
577
656
|
menu,
|
|
578
657
|
body,
|
|
579
658
|
React.createElement('div', { className: 'dsh-pu-card-foot' },
|
|
@@ -861,6 +940,95 @@ window.__ModuleLoader__.load({
|
|
|
861
940
|
}
|
|
862
941
|
return { level: 'err', label: '查询失败' + (qs.err ? ':' + qs.err : ''), clickable: true, detailKind: 'err', dotCls: ' zGbnIq_credentialDotMissing', detailText: '查询失败:' + (qs.err || '未知错误') };
|
|
863
942
|
}
|
|
943
|
+
// 卡片设置页:5 个开关控制卡片信息模块显示;即时生效 + 保存失败反馈 + 恢复默认
|
|
944
|
+
function CardSettingsPanel() {
|
|
945
|
+
var s = useSettings();
|
|
946
|
+
var card = s.card || {};
|
|
947
|
+
// 持久化失败提示(setSettings 回调收到非空 err 时显示;下次成功自动清除)
|
|
948
|
+
var [persistFailed, setPersistFailed] = useState(false);
|
|
949
|
+
var persistErrTimer = useRef(null);
|
|
950
|
+
useEffect(function () {
|
|
951
|
+
var dispose = subscribeSettings(function (err) {
|
|
952
|
+
if (err) {
|
|
953
|
+
setPersistFailed(true);
|
|
954
|
+
window.clearTimeout(persistErrTimer.current);
|
|
955
|
+
persistErrTimer.current = window.setTimeout(function () { setPersistFailed(false); }, 4000);
|
|
956
|
+
} else {
|
|
957
|
+
setPersistFailed(false);
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
return function () {
|
|
961
|
+
dispose();
|
|
962
|
+
window.clearTimeout(persistErrTimer.current);
|
|
963
|
+
};
|
|
964
|
+
}, []);
|
|
965
|
+
var [resetArm, setResetArm] = useState(false);
|
|
966
|
+
var resetTimer = useRef(null);
|
|
967
|
+
useEffect(function () {
|
|
968
|
+
return function () { window.clearTimeout(resetTimer.current); };
|
|
969
|
+
}, []);
|
|
970
|
+
function armReset() {
|
|
971
|
+
setResetArm(true);
|
|
972
|
+
window.clearTimeout(resetTimer.current);
|
|
973
|
+
resetTimer.current = window.setTimeout(function () { setResetArm(false); }, 4000);
|
|
974
|
+
}
|
|
975
|
+
function doReset() {
|
|
976
|
+
setResetArm(false);
|
|
977
|
+
window.clearTimeout(resetTimer.current);
|
|
978
|
+
setSettings({ visible: true, card: defaultCard() });
|
|
979
|
+
}
|
|
980
|
+
function toggle(key) {
|
|
981
|
+
setSettings(function (prev) {
|
|
982
|
+
var cur = (prev && prev.card) || {};
|
|
983
|
+
var next = Object.assign({}, cur);
|
|
984
|
+
next[key] = !cardModuleOn(cur, key);
|
|
985
|
+
return { card: next };
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
var rows = [
|
|
989
|
+
{ key: 'showMainNumber', label: zh.showMainNumber, hint: zh.showMainNumberHint },
|
|
990
|
+
{ key: 'showSubRow', label: zh.showSubRow, hint: zh.showSubRowHint },
|
|
991
|
+
{ key: 'showWindowBars', label: zh.showWindowBars, hint: zh.showWindowBarsHint },
|
|
992
|
+
{ key: 'showChip', label: zh.showChip, hint: zh.showChipHint },
|
|
993
|
+
{ key: 'showProviderName', label: zh.showProviderName, hint: zh.showProviderNameHint },
|
|
994
|
+
];
|
|
995
|
+
var cardOn = s.visible !== false;
|
|
996
|
+
var allOff = !rows.some(function (r) { return cardModuleOn(card, r.key); });
|
|
997
|
+
function switchRow(id, on, ariaLabel, text, hint, onChange) {
|
|
998
|
+
return React.createElement('div', { className: 'zGbnIq_rowCard' },
|
|
999
|
+
React.createElement('div', { className: 'zGbnIq_editorSwitchRow', style: { justifyContent: 'space-between' } },
|
|
1000
|
+
React.createElement('div', { className: 'dsh-pu-switchRowText' },
|
|
1001
|
+
React.createElement('span', { className: 'dsh-pu-switchText' }, text),
|
|
1002
|
+
React.createElement('span', { className: 'zGbnIq_advancedHint' }, hint)),
|
|
1003
|
+
React.createElement('button', {
|
|
1004
|
+
type: 'button', role: 'switch', id: id,
|
|
1005
|
+
'aria-checked': on ? 'true' : 'false',
|
|
1006
|
+
'aria-label': ariaLabel,
|
|
1007
|
+
className: 'dsh-pu-switch' + (on ? ' dsh-pu-switch-on' : ''),
|
|
1008
|
+
onClick: onChange,
|
|
1009
|
+
}, React.createElement('span', { className: 'dsh-pu-switch-thumb' }))));
|
|
1010
|
+
}
|
|
1011
|
+
return React.createElement('div', { className: 'zGbnIq_section' },
|
|
1012
|
+
React.createElement('h2', { className: 'zGbnIq_title' }, zh.cardSettings),
|
|
1013
|
+
React.createElement('p', { className: 'zGbnIq_intro' }, zh.cardSettingsDesc),
|
|
1014
|
+
persistFailed ? React.createElement('p', { className: 'zGbnIq_error' }, zh.saveFailed) : null,
|
|
1015
|
+
React.createElement('div', { className: 'zGbnIq_rows' },
|
|
1016
|
+
switchRow('pu-switch-visible', cardOn, zh.showCard, zh.showCard, zh.showCardHint,
|
|
1017
|
+
function () { setSettings({ visible: !cardOn }); }),
|
|
1018
|
+
allOff ? React.createElement('p', { className: 'zGbnIq_advancedHint', style: { margin: '0' } }, zh.allModulesOff) : null,
|
|
1019
|
+
rows.map(function (r) {
|
|
1020
|
+
return switchRow('pu-switch-' + r.key, cardModuleOn(card, r.key), r.label, r.label, r.hint,
|
|
1021
|
+
function () { toggle(r.key); });
|
|
1022
|
+
})),
|
|
1023
|
+
React.createElement('div', { className: 'zGbnIq_editorActions', style: { marginTop: '4px' } },
|
|
1024
|
+
React.createElement('button', {
|
|
1025
|
+
type: 'button',
|
|
1026
|
+
className: 'zGbnIq_secondaryButton',
|
|
1027
|
+
'data-arm': resetArm ? 'true' : undefined,
|
|
1028
|
+
'aria-label': resetArm ? zh.resetCardConfirm : zh.resetCard,
|
|
1029
|
+
onClick: resetArm ? doReset : armReset,
|
|
1030
|
+
}, resetArm ? zh.resetCardConfirm : zh.resetCard)));
|
|
1031
|
+
}
|
|
864
1032
|
function SettingsCard() {
|
|
865
1033
|
var s = useSettings();
|
|
866
1034
|
var providers = useProviders();
|
|
@@ -1212,12 +1380,15 @@ window.__ModuleLoader__.load({
|
|
|
1212
1380
|
React.createElement('button', { type: 'button', className: 'zGbnIq_primaryButton', disabled: busy, onClick: saveEdit }, '保存')));
|
|
1213
1381
|
}
|
|
1214
1382
|
|
|
1215
|
-
// 插件页同款二级菜单(官方 dsh-client-ui-settings-plugins 结构):提供方设置 / 用量统计
|
|
1383
|
+
// 插件页同款二级菜单(官方 dsh-client-ui-settings-plugins 结构):提供方设置 / 用量统计 / 卡片设置 三个互不影响的分页
|
|
1216
1384
|
var tabsList = [
|
|
1217
1385
|
{ id: 'providers', label: '提供方设置' },
|
|
1218
1386
|
{ id: 'usage', label: '用量统计' },
|
|
1387
|
+
{ id: 'card-settings', label: zh.cardSettings },
|
|
1219
1388
|
];
|
|
1220
1389
|
var [tab, setTab] = useState('providers');
|
|
1390
|
+
// 卡片因 visible=false 或全部模块关闭而隐藏时,在提供方页顶部给出可恢复的提示(卡片设置 tab 有恢复入口)
|
|
1391
|
+
var cardHidden = !s.visible || !CARD_MODULES.some(function (m) { return cardModuleOn(s.card, m.key); });
|
|
1221
1392
|
var tabsRef = useRef([]);
|
|
1222
1393
|
function onTabKey(e, idx) {
|
|
1223
1394
|
var len = tabsList.length;
|
|
@@ -1238,6 +1409,7 @@ window.__ModuleLoader__.load({
|
|
|
1238
1409
|
var providersPanel = React.createElement('div', { className: 'zGbnIq_section' },
|
|
1239
1410
|
React.createElement('h2', { className: 'zGbnIq_title' }, '提供方'),
|
|
1240
1411
|
React.createElement('p', { className: 'zGbnIq_intro' }, '填入各供应方的 Key 引用即可查询其用量与余额。'),
|
|
1412
|
+
cardHidden ? React.createElement('p', { className: 'dsh-pu-cardEmpty' }, zh.allModulesOff) : null,
|
|
1241
1413
|
React.createElement('ul', { className: 'zGbnIq_rows' },
|
|
1242
1414
|
providers.length === 0
|
|
1243
1415
|
? React.createElement('li', { className: 'zGbnIq_rowCard' },
|
|
@@ -1268,6 +1440,9 @@ window.__ModuleLoader__.load({
|
|
|
1268
1440
|
var usagePanel = React.createElement('div', { className: 'pbvGtq_panel', role: 'tabpanel', id: 'pu-tab-usage', 'aria-labelledby': 'pu-tab-btn-usage', hidden: tab !== 'usage' },
|
|
1269
1441
|
React.createElement(UsageStatsPage, { active: tab === 'usage' }));
|
|
1270
1442
|
|
|
1443
|
+
// 页面 3:卡片设置(卡片信息模块显示开关)
|
|
1444
|
+
var cardSettingsPanel = React.createElement('div', { className: 'pbvGtq_panel', role: 'tabpanel', id: 'pu-tab-card-settings', 'aria-labelledby': 'pu-tab-btn-card-settings', hidden: tab !== 'card-settings' },
|
|
1445
|
+
React.createElement(CardSettingsPanel));
|
|
1271
1446
|
// 二级菜单(插件页同款:下划线高亮 + 方向键切换)
|
|
1272
1447
|
var tabsBar = React.createElement('div', { className: 'pbvGtq_tabs', role: 'tablist', 'aria-label': '用量中心视图' },
|
|
1273
1448
|
tabsList.map(function (t, idx) {
|
|
@@ -1288,10 +1463,11 @@ window.__ModuleLoader__.load({
|
|
|
1288
1463
|
|
|
1289
1464
|
return React.createElement('div', { className: 'pbvGtq_section' },
|
|
1290
1465
|
React.createElement('h2', { className: 'pbvGtq_heading' }, '用量中心'),
|
|
1291
|
-
React.createElement('p', { className: 'pbvGtq_intro' },
|
|
1466
|
+
React.createElement('p', { className: 'pbvGtq_intro' }, zh.navDesc),
|
|
1292
1467
|
tabsBar,
|
|
1293
1468
|
React.createElement('div', { className: 'pbvGtq_panel', role: 'tabpanel', id: 'pu-tab-providers', 'aria-labelledby': 'pu-tab-btn-providers', hidden: tab !== 'providers' }, providersPanel),
|
|
1294
|
-
usagePanel
|
|
1469
|
+
usagePanel,
|
|
1470
|
+
cardSettingsPanel);
|
|
1295
1471
|
}
|
|
1296
1472
|
// 提供方单行:状态点 + 名称 + 编辑/删除 + 展开详情
|
|
1297
1473
|
// 状态判定全部交给 statusOf;本组件只做渲染;启用/暂停开关在编辑弹层里管理
|
package/lib/index.js
CHANGED
|
@@ -21,8 +21,8 @@ export const name = 'provider-usage'
|
|
|
21
21
|
|
|
22
22
|
/** 插件版本单一来源:package.json(UA 标识用;bundle 内嵌等读不到时回退字面量)。 */
|
|
23
23
|
const PLUGIN_VERSION = (() => {
|
|
24
|
-
try { return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version || '0.
|
|
25
|
-
catch { return '0.
|
|
24
|
+
try { return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version || '0.11.0' }
|
|
25
|
+
catch { return '0.11.0' }
|
|
26
26
|
})()
|
|
27
27
|
const USER_AGENT = 'dsh-provider-usage/' + PLUGIN_VERSION
|
|
28
28
|
|
package/package.json
CHANGED