dsh-peak-status 1.0.4 → 1.0.5
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 +5 -5
- package/README.zh-CN.md +6 -6
- package/lib/client.js +37 -21
- package/package.json +2 -2
- package/src/client.js +37 -21
package/README.md
CHANGED
|
@@ -17,20 +17,20 @@ DeepSeek's official peak/valley API pricing (effective 2026-08-17, weekends adju
|
|
|
17
17
|
|
|
18
18
|
Weekends (Saturday and Sunday) are charged at the valley price all day — no peak windows on weekends.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Per DeepSeek's peak/valley note, the only days that can peak are ordinary Monday–Friday working days:
|
|
21
21
|
|
|
22
22
|
| Day | State (Beijing time) |
|
|
23
23
|
| :-- | :-- |
|
|
24
24
|
| 法定节假日 (statutory holiday) | valley for the whole day, exactly like a weekend |
|
|
25
|
-
|
|
|
25
|
+
| 调休上班的周末 (a weekend worked) | valley for the whole day too — 调休 does not change billing |
|
|
26
26
|
|
|
27
|
-
So the chip shows 🟢 **国庆节** instead of a red peak on 1 October, and
|
|
27
|
+
So the chip shows 🟢 **国庆节** instead of a red peak on 1 October, and 🟢 **调休上班 · 谷价** on a 调休 Saturday.
|
|
28
28
|
|
|
29
29
|
## What you get
|
|
30
30
|
|
|
31
31
|
- A colored status dot — **red = peak, green = off-peak** — plus the live Beijing clock (`HH:MM:SS`, timezone `Asia/Shanghai`, independent of your machine's timezone)
|
|
32
32
|
- A countdown: `剩 3h 54m · 价格 ×2` during peak / `距高峰 3h 54m · 半价` off-peak
|
|
33
|
-
- Holiday awareness: on a 法定节假日 the chip names the festival (e.g. `国庆节`) and counts down to the first peak window after the break; on a
|
|
33
|
+
- Holiday awareness: on a 法定节假日 the chip names the festival (e.g. `国庆节`) and counts down to the first peak window after the break; on a 调休上班的周末 it shows all-day valley and tags the day
|
|
34
34
|
- Click the chip to expand a detail card: peak windows, the next transition with a `HH:MM:SS` countdown, and a progress bar of the current phase
|
|
35
35
|
- Fully themed with the web UI's native `--dsw-alias-*` variables — it blends into the interface instead of floating over it
|
|
36
36
|
- Mounted persistently: it survives dsh web restarts
|
|
@@ -65,7 +65,7 @@ The calendar (法定节假日 + 调休 makeup days) is fetched over the network,
|
|
|
65
65
|
|
|
66
66
|
Normalized days are cached in `localStorage` for 24 hours, so a restart or a spell offline still renders the right state, and the detail card always reports the source (`已同步 · jiejiariapi` / `未同步 · 暂按周末规则`).
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
Pricing follows DeepSeek's 峰谷时间说明: **调休上班的周末 and 中国法定节假日 are billed at the off-peak rate for the whole day**. The calendar supplies exactly those two labels — a 调休 day never gains a peak window.
|
|
69
69
|
|
|
70
70
|
## License
|
|
71
71
|
|
package/README.zh-CN.md
CHANGED
|
@@ -17,20 +17,20 @@ DeepSeek 官方峰谷定价(2026-08-17 生效,2026-08-23 起周末调整)
|
|
|
17
17
|
|
|
18
18
|
周末(周六、周日)全天按谷价计费,不设高峰时段。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
按 DeepSeek 峰谷时间说明,能有高峰窗口的只有"既非周六周日、也非法定节假日"的普通工作日:
|
|
21
21
|
|
|
22
22
|
| 日期 | 状态(北京时间) |
|
|
23
23
|
| :-- | :-- |
|
|
24
|
-
|
|
|
25
|
-
|
|
|
24
|
+
| 中国法定节假日 | 全天按空闲时段计费,与周末一致 |
|
|
25
|
+
| 调休上班的周末 | 同样全天按空闲时段计费(调休不改计费,只影响标签) |
|
|
26
26
|
|
|
27
|
-
所以 10 月 1
|
|
27
|
+
所以 10 月 1 日显示 🟢 **国庆节**、调休的周六显示 🟢 **调休上班 · 谷价**,两者都不进高峰。
|
|
28
28
|
|
|
29
29
|
## 功能
|
|
30
30
|
|
|
31
31
|
- 状态圆点——**红 = 高峰,绿 = 空闲**,外加实时北京时钟(`HH:MM:SS`,时区 `Asia/Shanghai`,与本机时区无关)
|
|
32
32
|
- 倒计时:高峰时显示 `剩 3h 54m · 价格 ×2`,空闲时显示 `距高峰 3h 54m · 半价`
|
|
33
|
-
- 节假日感知:法定节假日直接显示节日名(如
|
|
33
|
+
- 节假日感知:法定节假日直接显示节日名(如 `国庆节`),并倒计时到假期结束后的第一个高峰窗口;调休上班的周末显示全天谷价并标注该日
|
|
34
34
|
- 点击胶囊展开详情卡:高峰窗口、下一转折(含 `HH:MM:SS` 倒计时)、当前阶段进度条
|
|
35
35
|
- 全部使用 Web UI 原生 `--dsw-alias-*` 主题变量,与界面完全融合,没有悬浮贴片
|
|
36
36
|
- 持久挂载:重启 dsh web 后依然存在
|
|
@@ -65,7 +65,7 @@ dsh plugin --profile web add github:xiaoyi-xx/dsh-peak-status
|
|
|
65
65
|
|
|
66
66
|
归一化后的结果还会写入 `localStorage` 缓存 24 小时,所以重启或短暂断网时状态依旧正确;详情卡始终标注数据来源(`已同步 · jiejiariapi` / `未同步 · 暂按周末规则`)。
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
计费口径按 DeepSeek 峰谷时间说明:**调休上班的周末、中国法定节假日全天均按空闲时段计费**。日历提供的就是这两个标注——调休不会带来高峰窗口。
|
|
69
69
|
|
|
70
70
|
## 许可证
|
|
71
71
|
|
package/lib/client.js
CHANGED
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
* weekends: Saturday & Sunday all day at the valley price
|
|
14
14
|
* off-peak: everything else (priced at half of peak)
|
|
15
15
|
*
|
|
16
|
-
* The Chinese official work calendar refines
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* The Chinese official work calendar refines that rule: per DeepSeek's peak/
|
|
17
|
+
* valley note, 中国法定节假日 and 调休上班的周末 are valley for the whole day —
|
|
18
|
+
* only ordinary Monday–Friday working days can peak. The calendar is fetched
|
|
19
|
+
* over the network — the
|
|
19
20
|
* host half serves it same-origin, a CORS-capable public source and finally
|
|
20
21
|
* the plain weekend rule are the fallbacks — and cached in localStorage.
|
|
21
22
|
*
|
|
@@ -317,22 +318,34 @@
|
|
|
317
318
|
}
|
|
318
319
|
|
|
319
320
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
321
|
+
* 一天的"能否有高峰窗口 + 计费属性"。
|
|
322
|
+
*
|
|
323
|
+
* 官方口径(DeepSeek API 峰谷时间说明):**调休上班的周末、中国法定节假
|
|
324
|
+
* 日,全天均按空闲时段计费**。所以能进入高峰窗口的只有"既不是周六周日、
|
|
325
|
+
* 也不是法定节假日"的普通工作日:
|
|
326
|
+
* 法定节假日 → 全天谷价(哪怕落在周一~周五)
|
|
327
|
+
* 周六/周日(含调休上班) → 全天谷价(调休不改计费,只影响标签)
|
|
328
|
+
* 其余周一~周五 → 高峰窗口 09:00–12:00 / 14:00–18:00
|
|
329
|
+
* 无日历:退化成 1.0.3 的规则(周六周日谷价,其余工作日窗口)——对普通周
|
|
330
|
+
* 末与工作日而言与官方口径一致,唯一差别是节假日落在工作日时按高峰算。
|
|
331
|
+
*
|
|
323
332
|
* @param key - 'YYYY-MM-DD'。
|
|
324
333
|
* @param weekday - ISO 1=周一 … 7=周日。
|
|
325
334
|
* @param days - 该年归一化日历或 null。
|
|
335
|
+
* @returns {rest, kind, name},kind ∈ holiday | makeup | weekend | weekday。
|
|
326
336
|
*/
|
|
327
337
|
function classifyDay(key, weekday, days) {
|
|
328
338
|
var row = days === null || days === undefined ? null : days[key]
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return { rest:
|
|
339
|
+
var weekend = weekday === 6 || weekday === 7
|
|
340
|
+
var name = row === undefined || row === null ? '' : (row.name || '')
|
|
341
|
+
if (row !== undefined && row !== null && row.off === true) {
|
|
342
|
+
return { rest: true, kind: 'holiday', name: name }
|
|
333
343
|
}
|
|
334
|
-
if (
|
|
335
|
-
|
|
344
|
+
if (weekend) {
|
|
345
|
+
// 调休上班的周末依旧全天谷价,只换个标签说明"这天本该上班"。
|
|
346
|
+
return { rest: true, kind: row === undefined || row === null ? 'weekend' : 'makeup', name: name }
|
|
347
|
+
}
|
|
348
|
+
return { rest: false, kind: 'weekday', name: name }
|
|
336
349
|
}
|
|
337
350
|
|
|
338
351
|
function classifyOrdinal(ordinal, daysOf) {
|
|
@@ -370,10 +383,11 @@
|
|
|
370
383
|
|
|
371
384
|
/**
|
|
372
385
|
* Peak/off-peak state at one Beijing-time instant.
|
|
373
|
-
* The official work calendar decides which days may peak at all:
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* transitions are found by scanning days instead of weekday
|
|
386
|
+
* The official work calendar decides which days may peak at all: statutory
|
|
387
|
+
* holidays and every Saturday/Sunday (调休 makeup weekends included) are
|
|
388
|
+
* valley across their whole span, so both the current state and its
|
|
389
|
+
* neighbouring transitions are found by scanning days instead of weekday
|
|
390
|
+
* arithmetic.
|
|
377
391
|
* @param t - bjParts() result (calendar date, clock, ISO weekday).
|
|
378
392
|
* @param daysOf - year → normalized days; defaults to the loaded cache.
|
|
379
393
|
* @returns { peak, nextMin, daysAhead, nextOrdinal, nextWeekday, secsToNext, progress, day }
|
|
@@ -465,15 +479,17 @@
|
|
|
465
479
|
var boundaryLabel = fmtBoundaryLabel(s)
|
|
466
480
|
var stateWord = s.peak
|
|
467
481
|
? '高峰期'
|
|
468
|
-
: (day.kind === 'holiday'
|
|
482
|
+
: (day.kind === 'holiday'
|
|
483
|
+
? (day.name || '法定节假日')
|
|
484
|
+
: (day.kind === 'weekend' ? '周末谷价' : (day.kind === 'makeup' ? '调休上班 · 谷价' : '空闲期')))
|
|
469
485
|
var dayNote = day.kind === 'holiday'
|
|
470
486
|
? ('今日' + (day.name === '' ? '为法定节假日' : '为' + day.name) + ':全天按谷价计费。')
|
|
471
487
|
: (day.kind === 'makeup'
|
|
472
|
-
? ('今日为调休上班日(周' + WEEKDAY_LABELS[tick.weekday - 1] + '
|
|
488
|
+
? ('今日为调休上班日(周' + WEEKDAY_LABELS[tick.weekday - 1] + '):官方口径仍全天按空闲时段计费。')
|
|
473
489
|
: '')
|
|
474
490
|
var offNote = day.kind === 'holiday'
|
|
475
491
|
? ('(' + (day.name === '' ? '法定节假日' : day.name) + ' 全天谷价)')
|
|
476
|
-
: (day.kind === 'weekend' ? '(周末全天谷价)' : '')
|
|
492
|
+
: (day.kind === 'makeup' ? '(调休上班,全天谷价)' : (day.kind === 'weekend' ? '(周末全天谷价)' : ''))
|
|
477
493
|
var tooltip = (s.peak
|
|
478
494
|
? '高峰期(工作日 9:00-12:00 / 14:00-18:00):价格 = 空闲 ×2。' + boundaryLabel + ' 结束。'
|
|
479
495
|
: '空闲期:价格为高峰一半' + offNote + ',下一高峰 ' + boundaryLabel + '。') + dayNote + '点击展开详情'
|
|
@@ -533,8 +549,8 @@
|
|
|
533
549
|
'高峰窗口(工作日):09:00–12:00 / 14:00–18:00'),
|
|
534
550
|
react.createElement('div', { key: 'l2b', style: { color: day.rest ? OFF_COLOR : DIM, fontWeight: day.rest ? 600 : 400 } },
|
|
535
551
|
'法定节假日与周末(周六、周日):全天按谷价计费'),
|
|
536
|
-
react.createElement('div', { key: 'l2c', style: { color: day.kind === 'makeup' ?
|
|
537
|
-
'
|
|
552
|
+
react.createElement('div', { key: 'l2c', style: { color: day.kind === 'makeup' ? OFF_COLOR : DIM, fontWeight: day.kind === 'makeup' ? 600 : 400 } },
|
|
553
|
+
'调休上班的周末:仍全天按谷价计费(官方口径)'),
|
|
538
554
|
dayNote === '' ? null : react.createElement('div', { key: 'daynote', style: { color: color, fontWeight: 600 } }, dayNote),
|
|
539
555
|
react.createElement('div', { key: 'l3', style: { fontVariantNumeric: 'tabular-nums' } },
|
|
540
556
|
'下一转折:' + boundaryLabel + ' · 倒计时 ' + fmtDurFull(s.secsToNext)),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-peak-status",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Peak-hour indicator for the DSH web GUI: a native header chip showing whether the current Beijing time is inside DeepSeek's API peak window (weekdays 09:00–12:00 / 14:00–18:00; weekends all-day valley price), with a live clock, countdown, and ×2/off-peak pricing hints. Statutory holidays are valley all day
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "Peak-hour indicator for the DSH web GUI: a native header chip showing whether the current Beijing time is inside DeepSeek's API peak window (weekdays 09:00–12:00 / 14:00–18:00; weekends all-day valley price), with a live clock, countdown, and ×2/off-peak pricing hints. Statutory holidays and 调休上班的周末 are valley all day — only ordinary weekdays can peak; the official work calendar is fetched over the network and cached. · DSH Web GUI 高峰指示灯:原生会话头部胶囊,实时显示当前北京时间是否处于 DeepSeek API 高峰时段(工作日 9:00-12:00 / 14:00-18:00,周末全天谷价;法定节假日与调休上班的周末均全天谷价、只有普通工作日才有高峰,节假日表联网获取并缓存)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
package/src/client.js
CHANGED
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
* weekends: Saturday & Sunday all day at the valley price
|
|
14
14
|
* off-peak: everything else (priced at half of peak)
|
|
15
15
|
*
|
|
16
|
-
* The Chinese official work calendar refines
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* The Chinese official work calendar refines that rule: per DeepSeek's peak/
|
|
17
|
+
* valley note, 中国法定节假日 and 调休上班的周末 are valley for the whole day —
|
|
18
|
+
* only ordinary Monday–Friday working days can peak. The calendar is fetched
|
|
19
|
+
* over the network — the
|
|
19
20
|
* host half serves it same-origin, a CORS-capable public source and finally
|
|
20
21
|
* the plain weekend rule are the fallbacks — and cached in localStorage.
|
|
21
22
|
*
|
|
@@ -317,22 +318,34 @@
|
|
|
317
318
|
}
|
|
318
319
|
|
|
319
320
|
/**
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
321
|
+
* 一天的"能否有高峰窗口 + 计费属性"。
|
|
322
|
+
*
|
|
323
|
+
* 官方口径(DeepSeek API 峰谷时间说明):**调休上班的周末、中国法定节假
|
|
324
|
+
* 日,全天均按空闲时段计费**。所以能进入高峰窗口的只有"既不是周六周日、
|
|
325
|
+
* 也不是法定节假日"的普通工作日:
|
|
326
|
+
* 法定节假日 → 全天谷价(哪怕落在周一~周五)
|
|
327
|
+
* 周六/周日(含调休上班) → 全天谷价(调休不改计费,只影响标签)
|
|
328
|
+
* 其余周一~周五 → 高峰窗口 09:00–12:00 / 14:00–18:00
|
|
329
|
+
* 无日历:退化成 1.0.3 的规则(周六周日谷价,其余工作日窗口)——对普通周
|
|
330
|
+
* 末与工作日而言与官方口径一致,唯一差别是节假日落在工作日时按高峰算。
|
|
331
|
+
*
|
|
323
332
|
* @param key - 'YYYY-MM-DD'。
|
|
324
333
|
* @param weekday - ISO 1=周一 … 7=周日。
|
|
325
334
|
* @param days - 该年归一化日历或 null。
|
|
335
|
+
* @returns {rest, kind, name},kind ∈ holiday | makeup | weekend | weekday。
|
|
326
336
|
*/
|
|
327
337
|
function classifyDay(key, weekday, days) {
|
|
328
338
|
var row = days === null || days === undefined ? null : days[key]
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return { rest:
|
|
339
|
+
var weekend = weekday === 6 || weekday === 7
|
|
340
|
+
var name = row === undefined || row === null ? '' : (row.name || '')
|
|
341
|
+
if (row !== undefined && row !== null && row.off === true) {
|
|
342
|
+
return { rest: true, kind: 'holiday', name: name }
|
|
333
343
|
}
|
|
334
|
-
if (
|
|
335
|
-
|
|
344
|
+
if (weekend) {
|
|
345
|
+
// 调休上班的周末依旧全天谷价,只换个标签说明"这天本该上班"。
|
|
346
|
+
return { rest: true, kind: row === undefined || row === null ? 'weekend' : 'makeup', name: name }
|
|
347
|
+
}
|
|
348
|
+
return { rest: false, kind: 'weekday', name: name }
|
|
336
349
|
}
|
|
337
350
|
|
|
338
351
|
function classifyOrdinal(ordinal, daysOf) {
|
|
@@ -370,10 +383,11 @@
|
|
|
370
383
|
|
|
371
384
|
/**
|
|
372
385
|
* Peak/off-peak state at one Beijing-time instant.
|
|
373
|
-
* The official work calendar decides which days may peak at all:
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* transitions are found by scanning days instead of weekday
|
|
386
|
+
* The official work calendar decides which days may peak at all: statutory
|
|
387
|
+
* holidays and every Saturday/Sunday (调休 makeup weekends included) are
|
|
388
|
+
* valley across their whole span, so both the current state and its
|
|
389
|
+
* neighbouring transitions are found by scanning days instead of weekday
|
|
390
|
+
* arithmetic.
|
|
377
391
|
* @param t - bjParts() result (calendar date, clock, ISO weekday).
|
|
378
392
|
* @param daysOf - year → normalized days; defaults to the loaded cache.
|
|
379
393
|
* @returns { peak, nextMin, daysAhead, nextOrdinal, nextWeekday, secsToNext, progress, day }
|
|
@@ -465,15 +479,17 @@
|
|
|
465
479
|
var boundaryLabel = fmtBoundaryLabel(s)
|
|
466
480
|
var stateWord = s.peak
|
|
467
481
|
? '高峰期'
|
|
468
|
-
: (day.kind === 'holiday'
|
|
482
|
+
: (day.kind === 'holiday'
|
|
483
|
+
? (day.name || '法定节假日')
|
|
484
|
+
: (day.kind === 'weekend' ? '周末谷价' : (day.kind === 'makeup' ? '调休上班 · 谷价' : '空闲期')))
|
|
469
485
|
var dayNote = day.kind === 'holiday'
|
|
470
486
|
? ('今日' + (day.name === '' ? '为法定节假日' : '为' + day.name) + ':全天按谷价计费。')
|
|
471
487
|
: (day.kind === 'makeup'
|
|
472
|
-
? ('今日为调休上班日(周' + WEEKDAY_LABELS[tick.weekday - 1] + '
|
|
488
|
+
? ('今日为调休上班日(周' + WEEKDAY_LABELS[tick.weekday - 1] + '):官方口径仍全天按空闲时段计费。')
|
|
473
489
|
: '')
|
|
474
490
|
var offNote = day.kind === 'holiday'
|
|
475
491
|
? ('(' + (day.name === '' ? '法定节假日' : day.name) + ' 全天谷价)')
|
|
476
|
-
: (day.kind === 'weekend' ? '(周末全天谷价)' : '')
|
|
492
|
+
: (day.kind === 'makeup' ? '(调休上班,全天谷价)' : (day.kind === 'weekend' ? '(周末全天谷价)' : ''))
|
|
477
493
|
var tooltip = (s.peak
|
|
478
494
|
? '高峰期(工作日 9:00-12:00 / 14:00-18:00):价格 = 空闲 ×2。' + boundaryLabel + ' 结束。'
|
|
479
495
|
: '空闲期:价格为高峰一半' + offNote + ',下一高峰 ' + boundaryLabel + '。') + dayNote + '点击展开详情'
|
|
@@ -533,8 +549,8 @@
|
|
|
533
549
|
'高峰窗口(工作日):09:00–12:00 / 14:00–18:00'),
|
|
534
550
|
react.createElement('div', { key: 'l2b', style: { color: day.rest ? OFF_COLOR : DIM, fontWeight: day.rest ? 600 : 400 } },
|
|
535
551
|
'法定节假日与周末(周六、周日):全天按谷价计费'),
|
|
536
|
-
react.createElement('div', { key: 'l2c', style: { color: day.kind === 'makeup' ?
|
|
537
|
-
'
|
|
552
|
+
react.createElement('div', { key: 'l2c', style: { color: day.kind === 'makeup' ? OFF_COLOR : DIM, fontWeight: day.kind === 'makeup' ? 600 : 400 } },
|
|
553
|
+
'调休上班的周末:仍全天按谷价计费(官方口径)'),
|
|
538
554
|
dayNote === '' ? null : react.createElement('div', { key: 'daynote', style: { color: color, fontWeight: 600 } }, dayNote),
|
|
539
555
|
react.createElement('div', { key: 'l3', style: { fontVariantNumeric: 'tabular-nums' } },
|
|
540
556
|
'下一转折:' + boundaryLabel + ' · 倒计时 ' + fmtDurFull(s.secsToNext)),
|