dsh-offpeak 3.1.6 → 3.1.7

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.en.md CHANGED
@@ -56,7 +56,7 @@ dsh plugin --profile desktop add github:lizilong1993/dsh-offpeak
56
56
 
57
57
  # (3) local directory / Release asset (no permissions needed)
58
58
  dsh plugin --profile desktop add ./dsh-offpeak
59
- dsh plugin --profile desktop add ./dsh-offpeak-3.1.6.tgz
59
+ dsh plugin --profile desktop add ./dsh-offpeak-<version>.tgz
60
60
 
61
61
  dsh --profile desktop --dump-config # verify the composed patch layers
62
62
  ```
package/README.md CHANGED
@@ -56,7 +56,7 @@ dsh plugin --profile desktop add github:lizilong1993/dsh-offpeak
56
56
 
57
57
  # ③ 本地目录 / Release 资产(零权限)
58
58
  dsh plugin --profile desktop add ./dsh-offpeak
59
- dsh plugin --profile desktop add ./dsh-offpeak-3.1.6.tgz
59
+ dsh plugin --profile desktop add ./dsh-offpeak-<version>.tgz
60
60
 
61
61
  dsh --profile desktop --dump-config # 验证补丁分层
62
62
  ```
package/cordis.patch.yml CHANGED
@@ -1,9 +1,9 @@
1
- # dsh-offpeak bundle patch:一行装配进 profile。
2
- #
3
- # host 半(src/index.js)注册 sessionGuard 服务(冗余端口,供 input-traffic 适配)、
4
- # 高峰自动会话门(taskControl.pause/resume,缺失时回退锁等待队列)、
5
- # /session-guard/* 路由(路径保留旧名,input-traffic 依赖)与 设置→插件→offpeak 子板块。
6
- # 浏览器半(经 package.json dsh.client 声明)提供高峰面板(畅跑任务 + 拦截列表)。
7
- - insert:
8
- - id: offpeak
9
- name: dsh-offpeak
1
+ # dsh-offpeak bundle patch:一行装配进 profile。
2
+ #
3
+ # host 半(src/index.js)注册 sessionGuard 服务(冗余端口,供 input-traffic 适配)、
4
+ # 高峰自动会话门(taskControl.pause/resume,缺失时回退锁等待队列)、
5
+ # /session-guard/* 路由(路径保留旧名,input-traffic 依赖)与 设置→插件→offpeak 子板块。
6
+ # 浏览器半(经 package.json dsh.client 声明)提供高峰面板(畅跑任务 + 拦截列表)。
7
+ - insert:
8
+ - id: offpeak
9
+ name: dsh-offpeak
package/lib/client.js CHANGED
@@ -522,8 +522,8 @@ window.__ModuleLoader__.load({
522
522
  /* 「高峰拦截列表」面板(.sgMl* 由状态徽标与设置表单共用同一份样式) */
523
523
  .sgMlBody{margin-top:8px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:8px;background:var(--dsw-alias-bg-layer-2,transparent)}
524
524
  .sgMlBody *{box-sizing:border-box}
525
- .sgMlFilterRow{display:flex;align-items:center;gap:6px;padding-bottom:6px}
526
- .sgMlInput{flex:1;min-width:0;height:24px;padding:0 8px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.12));border-radius:6px;background:var(--dsw-alias-bg-layer-2,transparent);color:inherit;font:inherit;font-size:12px}
525
+ .sgMlFilterRow{display:flex;align-items:center;gap:6px;padding-bottom:6px;flex-wrap:wrap}
526
+ .sgMlInput{flex:1 1 160px;min-width:0;height:24px;padding:0 8px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.12));border-radius:6px;background:var(--dsw-alias-bg-layer-2,transparent);color:inherit;font:inherit;font-size:12px}
527
527
  .sgMlInput:disabled{opacity:.6;cursor:not-allowed}
528
528
  .sgMlError{color:var(--dsw-alias-state-error-primary,#dc2626);font-size:12px;line-height:18px;margin:6px 0 0;word-break:break-word}
529
529
  .sgMlPatterns{display:flex;align-items:center;flex-wrap:wrap;gap:6px;padding-bottom:6px;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.08))}
@@ -553,8 +553,8 @@ window.__ModuleLoader__.load({
553
553
  .sgMlModel{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
554
554
  .sgMlTag{flex:none;font-size:11px;color:var(--dsw-alias-label-tertiary,#6b7280);border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.08));border-radius:4px;padding:0 4px}
555
555
  .sgMlHint{color:var(--dsw-alias-label-tertiary,#6b7280);font-size:12px;line-height:18px;margin:6px 0 0}
556
- .sg-fr-panel,.sg-status-panel{position:absolute;bottom:calc(100% + 8px);right:0;z-index:40;width:448px;max-width:calc(100vw - 24px);box-sizing:border-box;padding:10px 12px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:10px;background:var(--dsw-specific-input-major,#fff);box-shadow:var(--dsw-elevation-panel,0 6px 24px rgba(0,0,0,.16));color:var(--dsw-alias-label-primary,#111);font-size:12px;line-height:1.5}
557
- .sg-status-panel{width:380px;z-index:45}
556
+ .sg-fr-panel,.sg-status-panel{position:absolute;bottom:calc(100% + 8px);right:0;z-index:40;width:min(448px,calc(100vw - 24px));max-height:min(70vh,560px);overflow:auto;overscroll-behavior:contain;box-sizing:border-box;padding:10px 12px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:10px;background:var(--dsw-specific-input-major,#fff);box-shadow:var(--dsw-elevation-panel,0 6px 24px rgba(0,0,0,.16));color:var(--dsw-alias-label-primary,#111);font-size:12px;line-height:1.5}
557
+ .sg-status-panel{width:min(380px,calc(100vw - 24px));z-index:45}
558
558
  .sg-status-panel *{box-sizing:border-box}
559
559
  .sg-fr-panel *{box-sizing:border-box}
560
560
  .sg-fr-head{display:flex;align-items:baseline;gap:8px;font-size:13px;font-weight:600;margin-bottom:8px}
@@ -628,6 +628,21 @@ window.__ModuleLoader__.load({
628
628
  .sg-fr-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:4px}
629
629
  .sg-fr-actions>button{height:24px;padding:0 10px;border:1px solid var(--dsw-alias-border-l3,rgba(0,0,0,.12));border-radius:6px;background:transparent;color:inherit;font:inherit;font-size:12px;cursor:pointer}
630
630
  .sg-fr-resume{border-color:var(--dsw-alias-state-success-primary,#30a46c)!important;color:var(--dsw-alias-state-success-primary,#30a46c)!important}
631
+ /* ── 响应式:窄窗口不裁切、日历改弹性列(v3.1.7)── */
632
+ .sg-dr-months{flex-wrap:wrap;justify-content:center;gap:10px}
633
+ .sg-dr-month{width:auto;flex:1 1 168px;min-width:0}
634
+ .sg-dr-panel{max-width:calc(100vw - 24px);box-sizing:border-box}
635
+ .sg-fr-list,.sgMlList{overflow-x:hidden}
636
+ @media (max-width:520px){
637
+ /* 单月:第二个日历换行后依然可读,但优先只显示一个(隐藏第二个) */
638
+ .sg-dr-month+.sg-dr-month{display:none}
639
+ .sg-dr-month{flex:1 1 100%;max-width:280px}
640
+ .sg-fr-panel,.sg-status-panel{right:auto;left:0;bottom:calc(100% + 6px)}
641
+ .sg-fr-bar{flex-wrap:wrap}
642
+ .sg-fr-bar-btn{flex:1 1 30%}
643
+ .sg-fr-hours{flex-wrap:wrap}
644
+ .sg-fr-hour{flex:1 1 100%}
645
+ }
631
646
  `;
632
647
  /** 注入一次(幂等;无 document 时静默跳过)。 */
633
648
  function injectClientCss() {
@@ -1240,6 +1255,7 @@ window.__ModuleLoader__.load({
1240
1255
  const [status, setStatus] = (0, react.useState)(null);
1241
1256
  const [freeRun, setFreeRun] = (0, react.useState)(EMPTY_FREE_RUN);
1242
1257
  const [open, setOpen] = (0, react.useState)(false);
1258
+ const rootRef = (0, react.useRef)(null);
1243
1259
  injectClientCss();
1244
1260
  (0, react.useEffect)(() => {
1245
1261
  if (!sessionId) return;
@@ -1261,6 +1277,17 @@ window.__ModuleLoader__.load({
1261
1277
  clearInterval(timer);
1262
1278
  };
1263
1279
  }, [sessionId]);
1280
+ (0, react.useEffect)(() => {
1281
+ if (!open) return;
1282
+ const onPointerDown = (ev) => {
1283
+ const root = rootRef.current;
1284
+ const target = ev.target;
1285
+ if (root === null || !(target instanceof Node)) return;
1286
+ if (!root.contains(target)) setOpen(false);
1287
+ };
1288
+ document.addEventListener("mousedown", onPointerDown);
1289
+ return () => document.removeEventListener("mousedown", onPointerDown);
1290
+ }, [open]);
1264
1291
  if (!status || !status.enabled) return null;
1265
1292
  const tasks = {
1266
1293
  intercepting: (status.modelPatterns ?? 0) > 0,
@@ -1268,6 +1295,7 @@ window.__ModuleLoader__.load({
1268
1295
  };
1269
1296
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1270
1297
  className: "sg-status-root",
1298
+ ref: rootRef,
1271
1299
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1272
1300
  type: "button",
1273
1301
  className: badgeClassNames(status),