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 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
- The Chinese official work calendar refines the weekend half of that rule:
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
- | 调休 makeup workday (a weekend worked) | the normal weekday windows apply |
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 🔴 peak windows on a 调休 Saturday.
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 调休 workday it shows the normal peak state and tags the day
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
- This is the *official Chinese work calendar* reading of the pricing: statutory holidays are valley and 调休 days are workdays. DeepSeek's published adjustment only mentions Saturday and Sunday if the calendar ever diverges from what is billed, the chip follows the calendar.
68
+ Pricing follows DeepSeek's 峰谷时间说明: **调休上班的周末 and 中国法定节假日 are billed at the off-peak rate for the whole day**. The calendar supplies exactly those two labelsa 调休 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
- 需要说明:这是按**中国官方工作日历**理解峰谷计价——法定节假日算谷价、调休日算工作日。DeepSeek 公布的调整只提到周六与周日;若官方日历与实际计费口径出现分歧,胶囊以日历为准。
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 the weekend half of that rule:
17
- * 法定节假日 (holiday rest days) are valley all day, and 调休 makeup days keep
18
- * the normal weekday windows. The calendar is fetched over the network — the
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
- * 无日历:退化成 1.0.3 的规则(周六周日休息,其余工作日)。
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
- if (row !== undefined && row !== null) {
330
- if (row.off === true) return { rest: true, kind: 'holiday', name: row.name || '' }
331
- if (weekday === 6 || weekday === 7) return { rest: false, kind: 'makeup', name: row.name || '' }
332
- return { rest: false, kind: 'weekday', name: row.name || '' }
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 (weekday === 6 || weekday === 7) return { rest: true, kind: 'weekend', name: '' }
335
- return { rest: false, kind: 'weekday', name: '' }
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: holiday
374
- * rest days are valley across their whole span and makeup workdays keep the
375
- * weekday windows, so both the current state and its neighbouring
376
- * transitions are found by scanning days instead of weekday arithmetic.
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' ? (day.name || '法定节假日') : (day.kind === 'weekend' ? '周末谷价' : '空闲期'))
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' ? PEAK_COLOR : DIM, fontWeight: day.kind === 'makeup' ? 600 : 400 } },
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",
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 and 调休 makeup workdays keep the weekday windows; the official work calendar is fetched over the network and cached. · DSH Web GUI 高峰指示灯:原生会话头部胶囊,实时显示当前北京时间是否处于 DeepSeek API 高峰时段(工作日 9:00-12:00 / 14:00-18:00,周末全天谷价;法定节假日全天谷价、调休上班日按工作日高峰,节假日表联网获取并缓存)。",
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 the weekend half of that rule:
17
- * 法定节假日 (holiday rest days) are valley all day, and 调休 makeup days keep
18
- * the normal weekday windows. The calendar is fetched over the network — the
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
- * 无日历:退化成 1.0.3 的规则(周六周日休息,其余工作日)。
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
- if (row !== undefined && row !== null) {
330
- if (row.off === true) return { rest: true, kind: 'holiday', name: row.name || '' }
331
- if (weekday === 6 || weekday === 7) return { rest: false, kind: 'makeup', name: row.name || '' }
332
- return { rest: false, kind: 'weekday', name: row.name || '' }
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 (weekday === 6 || weekday === 7) return { rest: true, kind: 'weekend', name: '' }
335
- return { rest: false, kind: 'weekday', name: '' }
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: holiday
374
- * rest days are valley across their whole span and makeup workdays keep the
375
- * weekday windows, so both the current state and its neighbouring
376
- * transitions are found by scanning days instead of weekday arithmetic.
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' ? (day.name || '法定节假日') : (day.kind === 'weekend' ? '周末谷价' : '空闲期'))
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' ? PEAK_COLOR : DIM, fontWeight: day.kind === 'makeup' ? 600 : 400 } },
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)),