dsh-dock 0.20.0 → 0.21.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/client.js CHANGED
@@ -2126,7 +2126,7 @@ __export(client_exports, {
2126
2126
  inject: () => inject
2127
2127
  });
2128
2128
  module.exports = __toCommonJS(client_exports);
2129
- var import_react24 = __toESM(require("react"), 1);
2129
+ var import_react26 = __toESM(require("react"), 1);
2130
2130
 
2131
2131
  // src/shared.js
2132
2132
  var import_react = __toESM(require("react"), 1);
@@ -3743,7 +3743,10 @@ function TokenLogChip(props) {
3743
3743
  if (!sid) return null;
3744
3744
  const t = snap.totals;
3745
3745
  const gone = isTokenlogRouteGone();
3746
- const label = gone ? "\u7528\u91CF\xB7\u672A\u542F\u7528" : snap.err && !t ? snap.err.includes("\u91CD\u542F") || snap.err.includes("\u542F\u7528") ? "\u7528\u91CF\xB7\u672A\u542F\u7528" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 " + fmtCostCny(t.cost, snap.rate) : "") : "\u26C1 \u2026";
3746
+ const hasData = !!t && !gone && !(snap.err && !t);
3747
+ const labelIcon = hasData ? "\u26C1 " : "";
3748
+ const labelMain = gone ? "\u7528\u91CF\xB7\u672A\u542F\u7528" : snap.err && !t ? snap.err.includes("\u91CD\u542F") || snap.err.includes("\u542F\u7528") ? "\u7528\u91CF\xB7\u672A\u542F\u7528" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? fmtCompact(t.totalTokens) : "\u2026";
3749
+ const labelExtra = hasData && t.cost > 0 ? " \xB7 " + fmtCostCny(t.cost, snap.rate) : "";
3747
3750
  const title = gone ? routeGoneMessage() + "\n\uFF08\u53EF\u5728\u529F\u80FD\u575E\u91CC\u542F\u7528\u300C\u7528\u91CF\u8BB0\u5F55\u300D\uFF09" : t ? "\u672C\u4F1A\u8BDD " + fmtNum(t.calls) + " \u6B21\u8C03\u7528 \xB7 " + fmtNum(t.totalTokens) + " Token \xB7 " + fmtCostCny(t.cost, snap.rate) + "\uFF08\u4F30\u7B97\uFF09\n\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55" : (snap.err ? snap.err + "\n" : "") + "\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55";
3748
3751
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
3749
3752
  "button",
@@ -3755,7 +3758,9 @@ function TokenLogChip(props) {
3755
3758
  onClick: () => openPanel("tokenlog", { sessionId: sid, navAt: Date.now() }),
3756
3759
  children: [
3757
3760
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dockchip-dot", style: { background: gone ? "var(--dsw-alias-label-tertiary,#8b95ab)" : "var(--dk-warn)" } }),
3758
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label })
3761
+ labelIcon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dockchip-ic", children: labelIcon }) : null,
3762
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: labelMain }),
3763
+ labelExtra ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dockchip-x", children: labelExtra }) : null
3759
3764
  ]
3760
3765
  }
3761
3766
  );
@@ -5438,10 +5443,10 @@ function chipBalanceText(p) {
5438
5443
  const b = p && p.balance;
5439
5444
  if (!b) return "\u4F59\u989D \u2026";
5440
5445
  if (b.status !== "ok") {
5441
- if (b.status === "login-required") return "\u4F59\u989D\xB7\u9700\u767B\u5F55";
5442
- if (b.status === "no-credential") return "\u4F59\u989D\xB7\u65E0\u5BC6\u94A5";
5443
- if (b.status === "unsupported") return "\u4F59\u989D\xB7\u4E0D\u652F\u6301";
5444
- return "\u4F59\u989D\xB7\u67E5\u8BE2\u5931\u8D25";
5446
+ if (b.status === "login-required") return "\u4F59\u989D \u9700\u767B\u5F55";
5447
+ if (b.status === "no-credential") return "\u4F59\u989D \u65E0\u5BC6\u94A5";
5448
+ if (b.status === "unsupported") return "\u4F59\u989D \u4E0D\u652F\u6301";
5449
+ return "\u4F59\u989D \u67E5\u8BE2\u5931\u8D25";
5445
5450
  }
5446
5451
  if (b.kind === "quota") {
5447
5452
  const v2 = Number(b.remaining);
@@ -5464,9 +5469,10 @@ function BalanceChip(props) {
5464
5469
  const def = selProvider || (data && data.default ? data.default.provider : null);
5465
5470
  const cur = def ? providers.find((p) => p.id === def) : null;
5466
5471
  const accent = cur ? accentOf(cur.id) : "#64748b";
5467
- const text = snap.error ? "\u4F59\u989D\xB7\u5931\u8D25" : !data ? snap.loading ? "\u4F59\u989D \u2026" : "\u4F59\u989D \u2014" : cur ? chipBalanceText(cur) : "\u4F59\u989D \u2014";
5472
+ const text = snap.error ? "\u4F59\u989D \u5931\u8D25" : !data ? snap.loading ? "\u4F59\u989D \u2026" : "\u4F59\u989D \u2014" : cur ? chipBalanceText(cur) : "\u4F59\u989D \u2014";
5468
5473
  const selModel = sel && (sel.model || sel.selected && sel.selected.model) || null;
5469
5474
  const title = cur ? (cur.displayName || cur.id) + (selModel ? " \xB7 \u5F53\u524D\u6A21\u578B " + selModel : "") + " \xB7 \u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u4F59\u989D\u8BE6\u60C5" : "\u70B9\u51FB\u6253\u5F00\u529F\u80FD\u575E \xB7 \u6A21\u578B\u4F59\u989D";
5475
+ const mm = /^(余额 )([\s\S]*)$/.exec(text);
5470
5476
  return import_react8.default.createElement(
5471
5477
  "button",
5472
5478
  {
@@ -5477,7 +5483,8 @@ function BalanceChip(props) {
5477
5483
  onClick: () => openPanel("balance", def ? { provider: def } : null)
5478
5484
  },
5479
5485
  import_react8.default.createElement("span", { className: "dockchip-dot", style: { background: accent } }),
5480
- import_react8.default.createElement("span", null, text)
5486
+ mm ? import_react8.default.createElement("span", { className: "dockchip-pre" }, mm[1]) : null,
5487
+ import_react8.default.createElement("span", null, mm ? mm[2] : text)
5481
5488
  );
5482
5489
  }
5483
5490
  var feature6 = {
@@ -7387,6 +7394,130 @@ function useVoiceClientEnabled() {
7387
7394
  }, []);
7388
7395
  return [on, set];
7389
7396
  }
7397
+ var CONFIG_SOURCE_KEY = "dsh-dock/notify/config-source/v1";
7398
+ var CLIENT_CONFIG_KEY = "dsh-dock/notify/client-config/v1";
7399
+ var CLIENT_CONFIG_FIELDS = [
7400
+ "notifyOnComplete",
7401
+ "notifyOnError",
7402
+ "notifyOnConfirm",
7403
+ "notifyOnStuck",
7404
+ "notifyCards",
7405
+ "cardMode",
7406
+ "notifyStayMs",
7407
+ "soundNotify",
7408
+ "soundEffect",
7409
+ "systemNotify",
7410
+ "voiceMode",
7411
+ "voiceOnComplete",
7412
+ "voiceOnError",
7413
+ "voiceOnConfirm",
7414
+ "voiceOnStuck",
7415
+ "voiceRate",
7416
+ "voiceVolume",
7417
+ "voiceLang",
7418
+ "voiceURI"
7419
+ ];
7420
+ function notifyConfigSource() {
7421
+ try {
7422
+ if (typeof localStorage === "undefined") return "server";
7423
+ return localStorage.getItem(CONFIG_SOURCE_KEY) === "client" ? "client" : "server";
7424
+ } catch {
7425
+ return "server";
7426
+ }
7427
+ }
7428
+ function setNotifyConfigSource(source) {
7429
+ try {
7430
+ if (typeof localStorage !== "undefined") localStorage.setItem(CONFIG_SOURCE_KEY, source === "client" ? "client" : "server");
7431
+ } catch {
7432
+ }
7433
+ }
7434
+ function readClientNotifyConfig() {
7435
+ try {
7436
+ if (typeof localStorage === "undefined") return null;
7437
+ const raw = localStorage.getItem(CLIENT_CONFIG_KEY);
7438
+ const obj = raw ? JSON.parse(raw) : null;
7439
+ return obj && typeof obj === "object" && !Array.isArray(obj) ? obj : null;
7440
+ } catch {
7441
+ return null;
7442
+ }
7443
+ }
7444
+ function writeClientNotifyConfig(cfg) {
7445
+ try {
7446
+ if (typeof localStorage !== "undefined") localStorage.setItem(CLIENT_CONFIG_KEY, JSON.stringify(cfg || {}));
7447
+ } catch {
7448
+ }
7449
+ }
7450
+ function pickClientConfig(serverCfg) {
7451
+ const src = serverCfg || {};
7452
+ const out = {};
7453
+ for (const key of CLIENT_CONFIG_FIELDS) {
7454
+ if (src[key] !== void 0) out[key] = src[key];
7455
+ }
7456
+ const matrix = {};
7457
+ const m = src.eventMatrix;
7458
+ if (m && typeof m === "object") {
7459
+ for (const [key, value] of Object.entries(m)) {
7460
+ if (typeof value === "boolean" && /^(card|sound|system|voice):/.test(key)) matrix[key] = value;
7461
+ }
7462
+ }
7463
+ out.eventMatrix = matrix;
7464
+ return out;
7465
+ }
7466
+ function mergeClientNotifyConfig(serverCfg, localCfg) {
7467
+ const server = serverCfg || {};
7468
+ const cfg = Object.assign({}, server, localCfg || {});
7469
+ for (const key of ["dingtalkEnabled", "dingtalkWebhook", "feishuEnabled", "feishuWebhook", "pushMode"]) {
7470
+ cfg[key] = server[key];
7471
+ }
7472
+ cfg.voiceNotify = server.voiceNotify === true;
7473
+ const matrix = Object.assign({}, server.eventMatrix || {});
7474
+ const localMatrix = localCfg && localCfg.eventMatrix || {};
7475
+ for (const [key, value] of Object.entries(localMatrix)) {
7476
+ if (typeof value === "boolean" && /^(card|sound|system|voice):/.test(key)) matrix[key] = value;
7477
+ }
7478
+ cfg.eventMatrix = matrix;
7479
+ return cfg;
7480
+ }
7481
+ function effectiveNotifyConfig(serverCfg) {
7482
+ const server = serverCfg || {};
7483
+ if (notifyConfigSource() !== "client") return server;
7484
+ const local = readClientNotifyConfig();
7485
+ if (!local) return server;
7486
+ return mergeClientNotifyConfig(server, local);
7487
+ }
7488
+ function useNotifyConfigSource() {
7489
+ const [source, setSource] = (0, import_react10.useState)(() => notifyConfigSource());
7490
+ const set = (0, import_react10.useCallback)((next) => {
7491
+ const value = next === "client" ? "client" : "server";
7492
+ setNotifyConfigSource(value);
7493
+ setSource(value);
7494
+ }, []);
7495
+ return [source, set];
7496
+ }
7497
+ var EVENT_CONFIG_KEY = {
7498
+ complete: "notifyOnComplete",
7499
+ error: "notifyOnError",
7500
+ confirm: "notifyOnConfirm",
7501
+ stuck: "notifyOnStuck"
7502
+ };
7503
+ var VOICE_EVENT_KEY = {
7504
+ complete: "voiceOnComplete",
7505
+ error: "voiceOnError",
7506
+ confirm: "voiceOnConfirm",
7507
+ stuck: "voiceOnStuck"
7508
+ };
7509
+ function eventEnabled(cfg, channel, event) {
7510
+ const key = channel + ":" + event;
7511
+ const matrix = cfg && cfg.eventMatrix;
7512
+ if (matrix && typeof matrix === "object" && typeof matrix[key] === "boolean") return matrix[key];
7513
+ if (channel === "voice") return !cfg || cfg[VOICE_EVENT_KEY[event]] !== false;
7514
+ return !cfg || cfg[EVENT_CONFIG_KEY[event]] !== false;
7515
+ }
7516
+ function withEventMatrix(cfg, channel, event, on) {
7517
+ const matrix = Object.assign({}, cfg && cfg.eventMatrix || {});
7518
+ matrix[channel + ":" + event] = !!on;
7519
+ return matrix;
7520
+ }
7390
7521
  function localVoices() {
7391
7522
  const s = synthOf();
7392
7523
  if (!s) return [];
@@ -7618,6 +7749,12 @@ var notifyStore = {
7618
7749
  this.emit();
7619
7750
  }
7620
7751
  },
7752
+ // 本机配置/配置来源变化:状态对象换一个浅拷贝,让订阅方(尤其浮层的 effect)重算。
7753
+ touch() {
7754
+ if (!this.snap.status) return;
7755
+ this.snap = Object.assign({}, this.snap, { status: Object.assign({}, this.snap.status) });
7756
+ this.emit();
7757
+ },
7621
7758
  refresh() {
7622
7759
  if (this.snap.loading) return Promise.resolve();
7623
7760
  this.snap = Object.assign({}, this.snap, { loading: true });
@@ -7763,12 +7900,12 @@ function NotifyOverlay(props) {
7763
7900
  const toastSeqRef = (0, import_react10.useRef)(0);
7764
7901
  const pushToast = (0, import_react10.useCallback)((toast) => {
7765
7902
  const st = notifyStore.snap.status;
7766
- const cfg = st && st.config;
7903
+ const cfg = st ? effectiveNotifyConfig(st.config) : null;
7767
7904
  if (cfg && cfg.notifyCards === false) return;
7768
7905
  setToasts((prev) => prev.concat([toast]).slice(-12));
7769
7906
  }, []);
7770
7907
  (0, import_react10.useEffect)(() => {
7771
- const cfg = snap.status && snap.status.config;
7908
+ const cfg = snap.status ? effectiveNotifyConfig(snap.status.config) : null;
7772
7909
  if (cfg && cfg.notifyCards === false) setToasts((prev) => prev.length ? [] : prev);
7773
7910
  }, [snap.status]);
7774
7911
  (0, import_react10.useEffect)(() => {
@@ -7800,7 +7937,7 @@ function NotifyOverlay(props) {
7800
7937
  for (const task of prev) {
7801
7938
  if (currIds.has(task.sessionId)) continue;
7802
7939
  const record = (st.recent || []).find((r) => r.sessionId === task.sessionId) || null;
7803
- handleTaskEnd(task, record, st.config || {});
7940
+ handleTaskEnd(task, record, effectiveNotifyConfig(st.config || {}));
7804
7941
  }
7805
7942
  }
7806
7943
  prevActiveRef.current = st.active.slice();
@@ -7808,7 +7945,7 @@ function NotifyOverlay(props) {
7808
7945
  (0, import_react10.useEffect)(() => {
7809
7946
  const st = snap.status;
7810
7947
  if (!st || !st.active) return;
7811
- const cfg = st.config || {};
7948
+ const cfg = effectiveNotifyConfig(st.config || {});
7812
7949
  const activeIds = new Set(st.active.map((x) => x.sessionId));
7813
7950
  for (const [sid, seen] of remindedApprovalsRef.current) {
7814
7951
  if (!activeIds.has(sid)) remindedApprovalsRef.current.delete(sid);
@@ -7824,10 +7961,10 @@ function NotifyOverlay(props) {
7824
7961
  const fresh = approvals.filter((a) => a && !seen.has(a.id));
7825
7962
  if (fresh.length === 0) continue;
7826
7963
  for (const a of fresh) seen.add(a.id);
7827
- if (voiceAllowed(cfg) && cfg.voiceOnConfirm !== false) {
7964
+ if (voiceAllowed(cfg) && eventEnabled(cfg, "voice", "confirm")) {
7828
7965
  speakVoice(confirmBroadcastText(task, fresh[0], cfg), cfg);
7829
7966
  }
7830
- if (cfg.notifyOnConfirm === false) continue;
7967
+ if (!eventEnabled(cfg, "card", "confirm")) continue;
7831
7968
  const toolName = fresh[0].toolName || "";
7832
7969
  const scene = toolLabel(toolName);
7833
7970
  const tone = cardTone(cfg);
@@ -7853,8 +7990,8 @@ function NotifyOverlay(props) {
7853
7990
  // 下面的对账 effect 据此自动收起卡片(处理完就不该再占着右上角)。
7854
7991
  approvalKeys: fresh.filter((a) => a && a.id).map((a) => task.sessionId + "|" + a.id)
7855
7992
  });
7856
- if (cfg.soundNotify !== false) playAskSound(cfg.soundEffect);
7857
- if (cfg.systemNotify && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
7993
+ if (cfg.soundNotify !== false && eventEnabled(cfg, "sound", "confirm")) playAskSound(cfg.soundEffect);
7994
+ if (cfg.systemNotify && eventEnabled(cfg, "system", "confirm") && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
7858
7995
  try {
7859
7996
  new Notification("dsh \u4EFB\u52A1\u9700\u8981\u786E\u8BA4", {
7860
7997
  body: (task.title || "(\u65E0\u6807\u9898)") + " \xB7 " + (toolName || "\u5DE5\u5177") + " \u7B49\u5F85\u786E\u8BA4",
@@ -7868,7 +8005,7 @@ function NotifyOverlay(props) {
7868
8005
  (0, import_react10.useEffect)(() => {
7869
8006
  const st = snap.status;
7870
8007
  if (!st || !st.active) return;
7871
- const cfg = st.config || {};
8008
+ const cfg = effectiveNotifyConfig(st.config || {});
7872
8009
  const activeIds = new Set(st.active.map((x) => x.sessionId));
7873
8010
  for (const [sid, seen] of remindedQuestionsRef.current) {
7874
8011
  if (!activeIds.has(sid)) remindedQuestionsRef.current.delete(sid);
@@ -7884,10 +8021,10 @@ function NotifyOverlay(props) {
7884
8021
  const fresh = questions.filter((q) => q && q.id && !seen.has(q.id));
7885
8022
  if (fresh.length === 0) continue;
7886
8023
  for (const q of fresh) seen.add(q.id);
7887
- if (voiceAllowed(cfg) && cfg.voiceOnConfirm !== false) {
8024
+ if (voiceAllowed(cfg) && eventEnabled(cfg, "voice", "confirm")) {
7888
8025
  speakVoice(questionBroadcastText(task, fresh[0], cfg), cfg);
7889
8026
  }
7890
- if (cfg.notifyOnConfirm === false) continue;
8027
+ if (!eventEnabled(cfg, "card", "confirm")) continue;
7891
8028
  const tone = cardTone(cfg);
7892
8029
  const head = fresh[0].header || "";
7893
8030
  const body = fresh[0].question || "";
@@ -7908,8 +8045,8 @@ function NotifyOverlay(props) {
7908
8045
  // 与这批提问绑定:回答落地后宿主把它们移出 questions,下面的对账 effect 据此收起
7909
8046
  questionKeys: fresh.map((q) => task.sessionId + "|" + q.id)
7910
8047
  });
7911
- if (cfg.soundNotify !== false) playAskSound(cfg.soundEffect);
7912
- if (cfg.systemNotify && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
8048
+ if (cfg.soundNotify !== false && eventEnabled(cfg, "sound", "confirm")) playAskSound(cfg.soundEffect);
8049
+ if (cfg.systemNotify && eventEnabled(cfg, "system", "confirm") && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
7913
8050
  try {
7914
8051
  new Notification("dsh \u4EFB\u52A1\u9700\u8981\u4F60\u56DE\u7B54", {
7915
8052
  body: (task.title || "(\u65E0\u6807\u9898)") + " \xB7 " + (head || "\u6709\u4E00\u95EE\u5728\u7B49\u4F60\u9009\u62E9"),
@@ -7964,7 +8101,7 @@ function NotifyOverlay(props) {
7964
8101
  (0, import_react10.useEffect)(() => {
7965
8102
  const st = snap.status;
7966
8103
  if (!st || !st.active) return;
7967
- const cfg = st.config || {};
8104
+ const cfg = effectiveNotifyConfig(st.config || {});
7968
8105
  const now = st.now || Date.now();
7969
8106
  const activeIds = new Set(st.active.map((x) => x.sessionId));
7970
8107
  for (const sid of Array.from(stuckSeenRef.current.keys())) {
@@ -7989,10 +8126,10 @@ function NotifyOverlay(props) {
7989
8126
  const prev = stuckSeenRef.current.get(task.sessionId);
7990
8127
  if (prev === lastAct) continue;
7991
8128
  stuckSeenRef.current.set(task.sessionId, lastAct);
7992
- if (voiceAllowed(cfg) && cfg.voiceOnStuck !== false) {
8129
+ if (voiceAllowed(cfg) && eventEnabled(cfg, "voice", "stuck")) {
7993
8130
  speakVoice(stuckBroadcastText(task, Object.assign({}, cfg, { stuckMs })), cfg);
7994
8131
  }
7995
- if (cfg.notifyOnStuck === false) continue;
8132
+ if (!eventEnabled(cfg, "card", "stuck")) continue;
7996
8133
  const label = task.isSubtask ? "\u5B50\u4EFB\u52A1" : "\u4E3B\u4EFB\u52A1";
7997
8134
  const title = task.title || "(\u65E0\u6807\u9898)";
7998
8135
  const tool = task.lastToolName || "";
@@ -8038,43 +8175,48 @@ function NotifyOverlay(props) {
8038
8175
  const reason = record && record.endReason || "";
8039
8176
  const success = isSuccessReason2(reason);
8040
8177
  const info = endInfo(reason);
8041
- const wanted = success ? cfg.notifyOnComplete : cfg.notifyOnError;
8042
- if (voiceAllowed(cfg) && (success ? cfg.voiceOnComplete !== false : cfg.voiceOnError !== false)) {
8178
+ const event = success ? "complete" : "error";
8179
+ const cardWanted = eventEnabled(cfg, "card", event);
8180
+ const soundWanted = cfg.soundNotify !== false && eventEnabled(cfg, "sound", event);
8181
+ const systemWanted = !!cfg.systemNotify && eventEnabled(cfg, "system", event);
8182
+ if (voiceAllowed(cfg) && eventEnabled(cfg, "voice", event)) {
8043
8183
  speakVoice(endBroadcastText(success, record, task, cfg), cfg);
8044
8184
  }
8045
- if (wanted === false) return;
8046
8185
  const models = record && record.models && record.models.length ? record.models.join(", ") : task.models && task.models.length ? task.models.join(", ") : "\u672A\u77E5\u6A21\u578B";
8047
8186
  const provider = record && record.provider || task.provider || "";
8048
8187
  const startTs = record && record.startTime || task.startTime;
8049
8188
  const endTs = record && record.endTime || Date.now();
8050
- const tone = cardTone(cfg);
8051
8189
  const durText = fmtDur(record && record.duration || endTs - startTs);
8052
- const lines = ["\u4EFB\u52A1\uFF1A" + (record && record.title || task.title || "(\u65E0\u6807\u9898)")];
8053
- if (tone !== "brief") lines.push("\u6A21\u578B\uFF1A" + models + (provider ? "\uFF08" + provider + "\uFF09" : ""));
8054
- lines.push(tone === "brief" ? "\u8017\u65F6\uFF1A" + durText : "\u8017\u65F6\uFF1A" + durText + "\uFF08" + fmtTime2(startTs) + " \u2192 " + fmtTime2(endTs) + "\uFF09");
8055
- if (tone === "detailed") {
8056
- lines.push("\u56DE\u5408 " + (record && record.turns || task.turns || 0) + " \xB7 \u6B65\u9AA4 " + (record && record.steps || task.steps || 0) + (record && record.toolCalls || task.toolCalls ? " \xB7 \u5DE5\u5177 " + (record && record.toolCalls || task.toolCalls) + " \u6B21" : ""));
8057
- lines.push("Token\uFF1A\u8F93\u5165 " + fmtNum2(record && record.inputTokens || task.inputTokens) + " / \u8F93\u51FA " + fmtNum2(record && record.outputTokens || task.outputTokens));
8058
- if (record && record.lastText) lines.push("\u6458\u8981\uFF1A" + truncate2(record.lastText, 140));
8059
- if (!success && record && record.errorMessage) lines.push("\u9519\u8BEF\uFF1A" + truncate2(record.errorMessage, 120));
8060
- }
8061
8190
  const title = success ? "\u4EFB\u52A1\u5B8C\u6210" : "\u4EFB\u52A1" + info.label;
8062
- pushToast({
8063
- id: ++toastSeqRef.current,
8064
- kind: success ? "success" : info.cls === "err" ? "error" : "warn",
8065
- title,
8066
- body: lines.join("\n"),
8067
- // 绑定会话:点卡片直达该会话;用户点进这个会话(侧栏选中)也视为
8068
- // 看到了结果,巡检 effect 据此自动收起卡片。没看过就一直挂着。
8069
- // sessionId 是权威标识(跳转/对账都用它),标题只作旧宿主回退。
8070
- sessionId: task.sessionId || "",
8071
- sessionTitle: record && record.title || task.title || ""
8072
- });
8073
- if (cfg.soundNotify !== false) playDoneSound(success, cfg.soundEffect);
8074
- if (cfg.systemNotify && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
8191
+ const showTitle = record && record.title || task.title || "(\u65E0\u6807\u9898)";
8192
+ if (cardWanted) {
8193
+ const tone = cardTone(cfg);
8194
+ const lines = ["\u4EFB\u52A1\uFF1A" + showTitle];
8195
+ if (tone !== "brief") lines.push("\u6A21\u578B\uFF1A" + models + (provider ? "\uFF08" + provider + "\uFF09" : ""));
8196
+ lines.push(tone === "brief" ? "\u8017\u65F6\uFF1A" + durText : "\u8017\u65F6\uFF1A" + durText + "\uFF08" + fmtTime2(startTs) + " \u2192 " + fmtTime2(endTs) + "\uFF09");
8197
+ if (tone === "detailed") {
8198
+ lines.push("\u56DE\u5408 " + (record && record.turns || task.turns || 0) + " \xB7 \u6B65\u9AA4 " + (record && record.steps || task.steps || 0) + (record && record.toolCalls || task.toolCalls ? " \xB7 \u5DE5\u5177 " + (record && record.toolCalls || task.toolCalls) + " \u6B21" : ""));
8199
+ lines.push("Token\uFF1A\u8F93\u5165 " + fmtNum2(record && record.inputTokens || task.inputTokens) + " / \u8F93\u51FA " + fmtNum2(record && record.outputTokens || task.outputTokens));
8200
+ if (record && record.lastText) lines.push("\u6458\u8981\uFF1A" + truncate2(record.lastText, 140));
8201
+ if (!success && record && record.errorMessage) lines.push("\u9519\u8BEF\uFF1A" + truncate2(record.errorMessage, 120));
8202
+ }
8203
+ pushToast({
8204
+ id: ++toastSeqRef.current,
8205
+ kind: success ? "success" : info.cls === "err" ? "error" : "warn",
8206
+ title,
8207
+ body: lines.join("\n"),
8208
+ // 绑定会话:点卡片直达该会话;用户点进这个会话(侧栏选中)也视为
8209
+ // 看到了结果,巡检 effect 据此自动收起卡片。没看过就一直挂着。
8210
+ // sessionId 是权威标识(跳转/对账都用它),标题只作旧宿主回退。
8211
+ sessionId: task.sessionId || "",
8212
+ sessionTitle: showTitle
8213
+ });
8214
+ }
8215
+ if (soundWanted) playDoneSound(success, cfg.soundEffect);
8216
+ if (systemWanted && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
8075
8217
  try {
8076
8218
  new Notification("dsh " + title, {
8077
- body: (record && record.title || task.title || "(\u65E0\u6807\u9898)") + " \xB7 " + fmtDur(record && record.duration || endTs - startTs),
8219
+ body: showTitle + " \xB7 " + durText,
8078
8220
  tag: "dsh-dock-notify-" + task.sessionId
8079
8221
  });
8080
8222
  } catch {
@@ -8102,11 +8244,115 @@ function NotifyOverlay(props) {
8102
8244
  }
8103
8245
  );
8104
8246
  }
8247
+ var MATRIX_COLUMNS = [
8248
+ { id: "card", label: "\u9875\u5185\u5361\u7247" },
8249
+ { id: "sound", label: "\u63D0\u793A\u97F3" },
8250
+ { id: "system", label: "\u7CFB\u7EDF\u901A\u77E5" },
8251
+ { id: "voice", label: "\u8BED\u97F3\u64AD\u62A5" },
8252
+ { id: "dingtalk", label: "\u9489\u9489" },
8253
+ { id: "feishu", label: "\u98DE\u4E66" }
8254
+ ];
8255
+ var MATRIX_EVENTS = [
8256
+ { id: "complete", label: "\u5B8C\u6210", desc: "\u4EFB\u52A1\u6B63\u5E38\u7ED3\u675F" },
8257
+ { id: "error", label: "\u5F02\u5E38", desc: "\u51FA\u9519 / \u4E2D\u6B62 / \u53D7\u963B / \u8FBE\u4E0A\u9650" },
8258
+ { id: "confirm", label: "\u9700\u786E\u8BA4 / \u9700\u56DE\u7B54", desc: "\u5DE5\u5177\u7B49\u6279\u51C6\u3001\u63D0\u95EE\u7B49\u56DE\u7B54" },
8259
+ { id: "stuck", label: "\u5361\u4F4F", desc: "\u7F16\u7A0B\u9636\u6BB5\u957F\u65F6\u95F4\u65E0\u6D3B\u52A8" }
8260
+ ];
8261
+ var MATRIX_SUPPORT = {
8262
+ card: ["complete", "error", "confirm", "stuck"],
8263
+ sound: ["complete", "error", "confirm"],
8264
+ system: ["complete", "error", "confirm"],
8265
+ voice: ["complete", "error", "confirm", "stuck"],
8266
+ dingtalk: ["complete", "error"],
8267
+ feishu: ["complete", "error"]
8268
+ };
8269
+ var MODE_OPTIONS = [["brief", "\u7B80\u6D01"], ["medium", "\u9002\u4E2D"], ["detailed", "\u8BE6\u7EC6"]];
8270
+ function ModePicker(props) {
8271
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-modes", children: MODE_OPTIONS.map(([value, label]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8272
+ "button",
8273
+ {
8274
+ type: "button",
8275
+ className: "dknt-miniswitch" + (props.value === value ? " on" : ""),
8276
+ title: props.title ? props.title + "\uFF08" + label + "\uFF09" : label,
8277
+ onClick: () => props.onChange(value),
8278
+ children: label
8279
+ },
8280
+ value
8281
+ )) });
8282
+ }
8283
+ function channelMasterOn(cfg, channel, voiceClientOn) {
8284
+ if (!cfg) return false;
8285
+ if (channel === "card") return cfg.notifyCards !== false;
8286
+ if (channel === "sound") return cfg.soundNotify !== false;
8287
+ if (channel === "system") return !!cfg.systemNotify;
8288
+ if (channel === "voice") return cfg.voiceNotify === true && voiceClientOn;
8289
+ if (channel === "dingtalk") return !!cfg.dingtalkEnabled;
8290
+ if (channel === "feishu") return !!cfg.feishuEnabled;
8291
+ return false;
8292
+ }
8293
+ function EventMatrix(props) {
8294
+ const { cfg, source, voiceClientOn, patch } = props;
8295
+ const toggle = (channel, event, on) => patch({ eventMatrix: withEventMatrix(cfg, channel, event, on) });
8296
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-matrix-wrap", children: [
8297
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-matrix", children: [
8298
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-matrix-row dknt-matrix-head", children: [
8299
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-matrix-event", children: "\u901A\u77E5\u4E8B\u4EF6" }),
8300
+ MATRIX_COLUMNS.map((column) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-matrix-col" + (channelMasterOn(cfg, column.id, voiceClientOn) ? " on" : ""), children: [
8301
+ column.label,
8302
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("em", { children: channelMasterOn(cfg, column.id, voiceClientOn) ? "\u5F00" : "\u5173" })
8303
+ ] }, column.id))
8304
+ ] }),
8305
+ MATRIX_EVENTS.map((ev) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-matrix-row", children: [
8306
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-matrix-event", children: [
8307
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("b", { children: ev.label }),
8308
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: ev.desc })
8309
+ ] }),
8310
+ MATRIX_COLUMNS.map((column) => {
8311
+ const supported = MATRIX_SUPPORT[column.id].indexOf(ev.id) !== -1;
8312
+ const serverOnly = source === "client" && (column.id === "dingtalk" || column.id === "feishu");
8313
+ if (!supported) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-cell dknt-cell-na", title: "\u8BE5\u6E20\u9053\u4E0D\u652F\u6301\u6B64\u4E8B\u4EF6", children: "\u2014" }, column.id);
8314
+ const on = eventEnabled(cfg, column.id, ev.id);
8315
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8316
+ "button",
8317
+ {
8318
+ type: "button",
8319
+ className: "dknt-cell" + (on ? " on" : "") + (serverOnly ? " disabled" : ""),
8320
+ role: "checkbox",
8321
+ "aria-checked": on,
8322
+ disabled: serverOnly,
8323
+ title: serverOnly ? "\u7FA4\u673A\u5668\u4EBA\u63A8\u9001\u7531\u670D\u52A1\u7AEF\u6267\u884C\uFF0C\u8BF7\u5207\u6362\u5230\u300C\u670D\u52A1\u7AEF\u914D\u7F6E\u300D\u4FEE\u6539" : on ? "\u53D6\u6D88\u8BE5\u4E8B\u4EF6\u901A\u8FC7\u6B64\u6E20\u9053\u63D0\u9192" : "\u8BA9\u8BE5\u4E8B\u4EF6\u901A\u8FC7\u6B64\u6E20\u9053\u63D0\u9192",
8324
+ onClick: () => {
8325
+ if (!serverOnly) toggle(column.id, ev.id, !on);
8326
+ },
8327
+ children: on ? "\u2713" : ""
8328
+ },
8329
+ column.id
8330
+ );
8331
+ })
8332
+ ] }, ev.id))
8333
+ ] }),
8334
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-matrix-legend", children: [
8335
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
8336
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "dknt-dot on" }),
8337
+ " \u5DF2\u52FE\u9009"
8338
+ ] }),
8339
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
8340
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "dknt-dot" }),
8341
+ " \u672A\u52FE\u9009"
8342
+ ] }),
8343
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u300C\u2014\u300D= \u8BE5\u6E20\u9053\u4E0D\u652F\u6301\u6B64\u4E8B\u4EF6" }),
8344
+ source === "client" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u9489\u9489 / \u98DE\u4E66\u4E3A\u670D\u52A1\u7AEF\u63A8\u9001\uFF0C\u9700\u5207\u56DE\u300C\u670D\u52A1\u7AEF\u914D\u7F6E\u300D\u4FEE\u6539" }) : null
8345
+ ] })
8346
+ ] });
8347
+ }
8105
8348
  function NotifyView(props) {
8106
8349
  const snap = useNotify();
8107
8350
  const voices = useLocalVoices();
8108
8351
  const [voiceClientOn, setVoiceClientOn] = useVoiceClientEnabled();
8109
- const [cfg, setCfg] = (0, import_react10.useState)(null);
8352
+ const [source, setSource] = useNotifyConfigSource();
8353
+ const [tab, setTab] = (0, import_react10.useState)("events");
8354
+ const [clientCfg, setClientCfg] = (0, import_react10.useState)(() => readClientNotifyConfig());
8355
+ const [serverDraft, setServerDraft] = (0, import_react10.useState)(null);
8110
8356
  const [saveErr, setSaveErr] = (0, import_react10.useState)("");
8111
8357
  const [testing, setTesting] = (0, import_react10.useState)(false);
8112
8358
  const [testState, setTestState] = (0, import_react10.useState)(null);
@@ -8116,21 +8362,36 @@ function NotifyView(props) {
8116
8362
  const pendingSavesRef = (0, import_react10.useRef)(0);
8117
8363
  const editingWebhookRef = (0, import_react10.useRef)(false);
8118
8364
  const editingFeishuRef = (0, import_react10.useRef)(false);
8365
+ const serverCfg = snap.status && snap.status.config;
8119
8366
  (0, import_react10.useEffect)(() => {
8120
- const c = snap.status && snap.status.config;
8121
- if (!c) return;
8367
+ if (!serverCfg) return;
8122
8368
  if (pendingSavesRef.current > 0 || editingWebhookRef.current || editingFeishuRef.current) return;
8123
- if (c !== cfgRef.current) {
8124
- cfgRef.current = c;
8125
- setCfg(Object.assign({}, c));
8369
+ if (serverCfg !== cfgRef.current) {
8370
+ cfgRef.current = serverCfg;
8371
+ setServerDraft(Object.assign({}, serverCfg));
8126
8372
  }
8127
8373
  }, [snap.status]);
8374
+ (0, import_react10.useEffect)(() => {
8375
+ if (source !== "client" || clientCfg || !serverCfg) return;
8376
+ const clone = pickClientConfig(serverCfg);
8377
+ writeClientNotifyConfig(clone);
8378
+ setClientCfg(clone);
8379
+ }, [source, clientCfg, serverCfg]);
8128
8380
  (0, import_react10.useEffect)(() => {
8129
8381
  if (!notifyStore.snap.status) notifyStore.refresh();
8130
8382
  }, []);
8383
+ const cfg = source === "client" ? clientCfg ? mergeClientNotifyConfig(serverCfg, clientCfg) : null : serverDraft || serverCfg;
8131
8384
  const patch = (p) => {
8132
8385
  setSaveErr("");
8133
- setCfg(Object.assign({}, cfg, p));
8386
+ if (source === "client") {
8387
+ const base = clientCfg || (serverCfg ? pickClientConfig(serverCfg) : {});
8388
+ const next = Object.assign({}, base, p);
8389
+ writeClientNotifyConfig(next);
8390
+ setClientCfg(next);
8391
+ notifyStore.touch();
8392
+ return Promise.resolve();
8393
+ }
8394
+ setServerDraft(Object.assign({}, cfg, p));
8134
8395
  pendingSavesRef.current++;
8135
8396
  return rpcCall3("config", p).then((d) => {
8136
8397
  pendingSavesRef.current--;
@@ -8140,6 +8401,22 @@ function NotifyView(props) {
8140
8401
  setSaveErr("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (e && e.message || String(e)));
8141
8402
  });
8142
8403
  };
8404
+ const chooseSource = (next) => {
8405
+ if (next === "client" && !clientCfg && serverCfg) {
8406
+ const clone = pickClientConfig(serverCfg);
8407
+ writeClientNotifyConfig(clone);
8408
+ setClientCfg(clone);
8409
+ }
8410
+ setSource(next);
8411
+ notifyStore.touch();
8412
+ };
8413
+ const copyFromServer = () => {
8414
+ if (!serverCfg) return;
8415
+ const clone = pickClientConfig(serverCfg);
8416
+ writeClientNotifyConfig(clone);
8417
+ setClientCfg(clone);
8418
+ notifyStore.touch();
8419
+ };
8143
8420
  const saveWebhook = async () => {
8144
8421
  if (!editingWebhookRef.current) return;
8145
8422
  const hook = String(cfg.dingtalkWebhook || "").trim();
@@ -8148,7 +8425,7 @@ function NotifyView(props) {
8148
8425
  const c = notifyStore.snap.status && notifyStore.snap.status.config;
8149
8426
  if (c && c !== cfgRef.current) {
8150
8427
  cfgRef.current = c;
8151
- setCfg(Object.assign({}, c));
8428
+ setServerDraft(Object.assign({}, c));
8152
8429
  }
8153
8430
  };
8154
8431
  const saveFeishuWebhook = async () => {
@@ -8159,7 +8436,7 @@ function NotifyView(props) {
8159
8436
  const c = notifyStore.snap.status && notifyStore.snap.status.config;
8160
8437
  if (c && c !== cfgRef.current) {
8161
8438
  cfgRef.current = c;
8162
- setCfg(Object.assign({}, c));
8439
+ setServerDraft(Object.assign({}, c));
8163
8440
  }
8164
8441
  };
8165
8442
  const runDingtalkTest = async () => {
@@ -8173,7 +8450,7 @@ function NotifyView(props) {
8173
8450
  notifyStore.applyConfig(d && d.config);
8174
8451
  editingWebhookRef.current = false;
8175
8452
  cfgRef.current = d && d.config || cfgRef.current;
8176
- setCfg(Object.assign({}, cfg, { dingtalkWebhook: hook }));
8453
+ setServerDraft(Object.assign({}, cfg, { dingtalkWebhook: hook }));
8177
8454
  }
8178
8455
  const r = await rpcCall3("test");
8179
8456
  setTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
@@ -8194,7 +8471,7 @@ function NotifyView(props) {
8194
8471
  notifyStore.applyConfig(d && d.config);
8195
8472
  editingFeishuRef.current = false;
8196
8473
  cfgRef.current = d && d.config || cfgRef.current;
8197
- setCfg(Object.assign({}, cfg, { feishuWebhook: hook }));
8474
+ setServerDraft(Object.assign({}, cfg, { feishuWebhook: hook }));
8198
8475
  }
8199
8476
  const r = await rpcCall3("test", { target: "feishu" });
8200
8477
  setFeishuTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
@@ -8225,484 +8502,508 @@ function NotifyView(props) {
8225
8502
  rows.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: snap.error ? "\u72B6\u6001\u4E0D\u53EF\u7528\uFF1A" + snap.error : snap.loading ? "\u6B63\u5728\u62C9\u53D6\u901A\u77E5\u72B6\u6001\u2026" : "\u7B49\u5F85\u901A\u77E5\u72B6\u6001" }, "load"));
8226
8503
  } else {
8227
8504
  rows.push(
8228
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec", children: [
8229
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec-head", children: [
8230
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-title", children: "\u901A\u77E5\u4E8B\u4EF6" }),
8231
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-sub", children: "\u54EA\u4E9B\u65F6\u523B\u63D0\u9192\u4F60\uFF1B\u4E0E\u3010\u4EFB\u52A1\u52A8\u753B\u3011\u7684\u52A8\u6548\u4E92\u4E0D\u4F9D\u8D56" })
8232
- ] }),
8233
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-rows-narrow", children: [
8234
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8235
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u9875\u5185\u5361\u7247" }),
8236
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8237
- "button",
8238
- {
8239
- type: "button",
8240
- className: "dknt-miniswitch" + (cfg.notifyCards !== false ? " on" : ""),
8241
- onClick: () => patch({ notifyCards: cfg.notifyCards === false }),
8242
- children: cfg.notifyCards !== false ? "\u5F00" : "\u5173"
8243
- }
8244
- ),
8245
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u53F3\u4FA7\u901A\u77E5\u5361\u7247\u603B\u5F00\u5173\uFF1A\u5173\u95ED\u540E\u4E0B\u9762\u5404\u7C7B\u5361\u7247\uFF08\u5B8C\u6210 / \u5F02\u5E38 / \u9700\u786E\u8BA4 / \u5361\u4F4F\uFF09\u4E00\u5F8B\u4E0D\u5F39\uFF0C\u5DF2\u6302\u7740\u7684\u4E00\u5E76\u6536\u8D77\uFF1B\u8BED\u97F3\u64AD\u62A5\u3001\u63D0\u793A\u97F3\u3001\u7CFB\u7EDF\u901A\u77E5\u3001\u9489\u9489\u98DE\u4E66\u63A8\u9001\u4E0D\u53D7\u5F71\u54CD" })
8246
- ] }),
8247
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8248
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u5B8C\u6210\u901A\u77E5" }),
8249
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8250
- "button",
8251
- {
8252
- type: "button",
8253
- className: "dknt-miniswitch" + (cfg.notifyOnComplete ? " on" : ""),
8254
- onClick: () => patch({ notifyOnComplete: !cfg.notifyOnComplete }),
8255
- children: cfg.notifyOnComplete ? "\u5F00" : "\u5173"
8256
- }
8257
- ),
8258
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u4EFB\u52A1\u6B63\u5E38\u5B8C\u6210\u65F6\u901A\u77E5" })
8259
- ] }),
8260
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8261
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u5F02\u5E38\u901A\u77E5" }),
8262
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8263
- "button",
8264
- {
8265
- type: "button",
8266
- className: "dknt-miniswitch" + (cfg.notifyOnError ? " on" : ""),
8267
- onClick: () => patch({ notifyOnError: !cfg.notifyOnError }),
8268
- children: cfg.notifyOnError ? "\u5F00" : "\u5173"
8269
- }
8270
- ),
8271
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u51FA\u9519 / \u4E2D\u6B62 / \u8FBE\u8F93\u51FA\u4E0A\u9650\u65F6\u901A\u77E5" })
8272
- ] }),
8273
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8274
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u9700\u786E\u8BA4\u63D0\u9192" }),
8275
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8276
- "button",
8277
- {
8278
- type: "button",
8279
- className: "dknt-miniswitch" + (cfg.notifyOnConfirm !== false ? " on" : ""),
8280
- onClick: () => patch({ notifyOnConfirm: cfg.notifyOnConfirm === false }),
8281
- children: cfg.notifyOnConfirm !== false ? "\u5F00" : "\u5173"
8282
- }
8283
- ),
8284
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u5DE5\u5177\u7B49\u4F60\u6279\u51C6\u3001\u6216\u4F1A\u8BDD\u63D0\u95EE\u7B49\u4F60\u9009\u7B54\u6848\u65F6\u5F39\u5361\u7247\u5E76\u54CD\u786E\u8BA4\u97F3\uFF1B\u5904\u7406\u5B8C\u81EA\u52A8\u6536\u8D77\uFF0C\u6CA1\u5904\u7406\u5B8C\u5C31\u4E00\u76F4\u663E\u793A\uFF08\u70B9\u5361\u7247\u76F4\u8FBE\u4F1A\u8BDD\uFF09\u3002\u8FD9\u4E24\u79CD\u300C\u505C\u5728\u539F\u5730\u7B49\u4EBA\u300D\u90FD\u4E0D\u7B97\u5361\u4F4F" })
8285
- ] }),
8286
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8287
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u5361\u4F4F\u63D0\u9192" }),
8288
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8289
- "button",
8290
- {
8291
- type: "button",
8292
- className: "dknt-miniswitch" + (cfg.notifyOnStuck !== false ? " on" : ""),
8293
- onClick: () => patch({ notifyOnStuck: cfg.notifyOnStuck === false }),
8294
- children: cfg.notifyOnStuck !== false ? "\u5F00" : "\u5173"
8295
- }
8296
- ),
8297
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7F16\u7A0B\u9636\u6BB5\u957F\u65F6\u95F4\u6CA1\u6709\u52A8\u9759\u65F6\u5F39\u5361\u7247\uFF0C\u5199\u660E\u662F\u4E3B\u4EFB\u52A1\u8FD8\u662F\u5B50\u4EFB\u52A1\u3001\u505C\u6EDE\u4E86\u591A\u4E45\u3001\u6700\u540E\u5728\u6267\u884C\u4EC0\u4E48\uFF1B\u6062\u590D\u6D3B\u52A8 / \u4EFB\u52A1\u7ED3\u675F\u81EA\u52A8\u6536\u8D77\uFF0C\u540C\u4E00\u505C\u70B9\u53EA\u5F39\u4E00\u6B21\u3002\u7B49\u6279\u51C6\u3001\u7B49\u56DE\u7B54\u3001\u547D\u4EE4\u8FD8\u5728\u8DD1\u3001\u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587\u7684\u4F1A\u8BDD\u90FD\u4E0D\u7B97\u5361\u4F4F\uFF08\u90A3\u4E9B\u90FD\u662F\u5728\u5E72\u6D3B\uFF0C\u522B\u91CD\u590D\u8F70\u70B8\uFF09\uFF08\u8BED\u97F3\u64AD\u62A5\u8D70\u300C\u8BED\u97F3\u64AD\u62A5\u300D\u533A\u7684\u5361\u4F4F\u5F00\u5173\uFF0C\u4E92\u4E0D\u5E72\u6270\uFF09" })
8298
- ] })
8299
- ] })
8300
- ] }, "events"),
8301
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec", children: [
8302
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec-head", children: [
8303
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-title", children: "\u63D0\u9192\u65B9\u5F0F" }),
8304
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-sub", children: "\u9875\u5185\u5361\u7247\u3001\u63D0\u793A\u97F3\u3001\u6D4F\u89C8\u5668\u7CFB\u7EDF\u901A\u77E5\u53EF\u81EA\u7531\u7EC4\u5408" })
8505
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-source", children: [
8506
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-source-info", children: [
8507
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-source-title", children: "\u914D\u7F6E\u6765\u6E90" }),
8508
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-source-sub", children: source === "server" ? "\u8BBE\u7F6E\u4FDD\u5B58\u5728\u670D\u52A1\u7AEF\uFF0C\u6240\u6709\u6D4F\u89C8\u5668/\u8BBE\u5907\u5171\u4EAB" : "\u8BBE\u7F6E\u53EA\u4FDD\u5B58\u5728\u5F53\u524D\u6D4F\u89C8\u5668\uFF0C\u4E0D\u5F71\u54CD\u5176\u4ED6\u4EBA" })
8305
8509
  ] }),
8306
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-rows-narrow", children: [
8307
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8308
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u5361\u7247\u53E3\u5F84" }),
8309
- [["brief", "\u7B80\u6D01"], ["medium", "\u9002\u4E2D"], ["detailed", "\u8BE6\u7EC6"]].map(([v, label]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8310
- "button",
8311
- {
8312
- type: "button",
8313
- className: "dknt-miniswitch" + (cardTone(cfg) === v ? " on" : ""),
8314
- style: { marginRight: 6 },
8315
- title: "\u53F3\u4FA7\u901A\u77E5\u5361\u7247\u6B63\u6587\u6309" + label + "\u6863\u663E\u793A",
8316
- onClick: () => patch({ cardMode: v }),
8317
- children: label
8318
- },
8319
- v
8320
- )),
8321
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u53F3\u4FA7\u5361\u7247\u6B63\u6587\u5199\u591A\u5C11\uFF08\u4E0E\u5404\u7C7B\u578B\u5F00\u5173\u3001\u8BED\u97F3\u64AD\u62A5\u4E92\u4E0D\u5F71\u54CD\uFF09\uFF1A\u7B80\u6D01\uFF1D\u4EFB\u52A1\u4E0E\u8017\u65F6 / \u8C01\u5361\u4F4F\uFF1B\u9002\u4E2D\uFF1D\u52A0\u6A21\u578B\u3001\u8D77\u6B62\u65F6\u95F4\u3001\u505C\u6EDE\u65F6\u957F\uFF1B\u8BE6\u7EC6\uFF1D\u5168\u90E8\uFF08\u56DE\u5408\u6B65\u9AA4\u3001Token\u3001\u6458\u8981\u6216\u9519\u8BEF\u3001\u6700\u540E\u52A8\u4F5C\uFF09" })
8322
- ] }),
8323
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8324
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u5361\u7247\u6536\u7EB3" }),
8325
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u6240\u6709\u5361\u7247\u90FD\u4E0D\u8D85\u65F6\u81EA\u52A8\u6D88\u5931\uFF1A\u7ED3\u675F\u5361\u7247\u6CA1\u770B\u8FC7\u5C31\u4E00\u76F4\u6302\u7740\uFF08\u540E\u53F0\u8DD1\u5B8C\u7684\u5207\u56DE\u6765\u4E5F\u5728\uFF09\uFF0C\u70B9\u5361\u7247\u76F4\u8FBE\u5BF9\u5E94\u4F1A\u8BDD\uFF0C\u6216\u70B9\u8FDB\u8BE5\u4F1A\u8BDD\uFF0C\u5361\u7247\u81EA\u52A8\u6536\u8D77\uFF1B\u9700\u786E\u8BA4\u5361\u7247\u6302\u5230\u5BA1\u6279\u5904\u7406\u5B8C\uFF1B\u5361\u4F4F\u5361\u7247\u6302\u5230\u6062\u590D\u6D3B\u52A8\u30023 \u5F20\u53CA\u4EE5\u4E0A\u81EA\u52A8\u53E0\u653E\u6210\u6807\u9898\u6761\uFF0C\u9F20\u6807\u79FB\u4E0A\u53BB\u6574\u4F53\u5C55\u5F00\uFF1B\u8981\u6574\u4F53\u4E0D\u5F39\u770B\u4E0A\u9762\u300C\u9875\u5185\u5361\u7247\u300D\u603B\u5F00\u5173" })
8326
- ] }),
8327
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8328
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u7CFB\u7EDF\u901A\u77E5" }),
8329
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8330
- "button",
8331
- {
8332
- type: "button",
8333
- className: "dknt-miniswitch" + (cfg.systemNotify ? " on" : ""),
8334
- onClick: () => enableSystemNotify(!cfg.systemNotify),
8335
- children: cfg.systemNotify ? "\u5F00" : "\u5173"
8336
- }
8337
- ),
8338
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: permNote })
8339
- ] }),
8340
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8341
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u63D0\u793A\u97F3" }),
8342
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8343
- "button",
8344
- {
8345
- type: "button",
8346
- className: "dknt-miniswitch" + (cfg.soundNotify !== false ? " on" : ""),
8347
- onClick: () => patch({ soundNotify: cfg.soundNotify === false }),
8348
- children: cfg.soundNotify !== false ? "\u5F00" : "\u5173"
8349
- }
8350
- ),
8351
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u4EFB\u52A1\u7ED3\u675F/\u9700\u786E\u8BA4\u65F6\u64AD\u653E\uFF08\u8BD5\u542C\u4E3A\u5148\u64AD\u5B8C\u6210\u97F3\u3001\u540E\u64AD\u5F02\u5E38\u97F3\uFF09" })
8352
- ] }),
8353
- cfg.soundNotify !== false ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-sounds", children: Object.keys(SOUND_LIBRARY).map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8510
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-seg", role: "group", "aria-label": "\u901A\u77E5\u914D\u7F6E\u6765\u6E90", children: [
8511
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8354
8512
  "button",
8355
8513
  {
8356
8514
  type: "button",
8357
- className: "dknt-sound" + (cfg.soundEffect === key ? " on" : ""),
8358
- onClick: () => patch({ soundEffect: key }),
8359
- children: [
8360
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sound-name", children: [
8361
- SOUND_LIBRARY[key].name,
8362
- cfg.soundEffect === key ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sound-cur", children: "\u2713" }) : null
8363
- ] }),
8364
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8365
- "span",
8366
- {
8367
- className: "dknt-sound-play",
8368
- role: "button",
8369
- tabIndex: 0,
8370
- title: "\u8BD5\u542C " + SOUND_LIBRARY[key].name,
8371
- onClick: (e) => {
8372
- e.stopPropagation();
8373
- previewSound(key);
8374
- },
8375
- onKeyDown: (e) => {
8376
- if (e.key === "Enter" || e.key === " ") {
8377
- e.preventDefault();
8378
- e.stopPropagation();
8379
- previewSound(key);
8380
- }
8381
- },
8382
- children: "\u25B6"
8383
- }
8384
- )
8385
- ]
8386
- },
8387
- key
8388
- )) }) : null
8389
- ] })
8390
- ] }, "style"),
8391
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec", children: [
8392
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec-head", children: [
8393
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-title", children: "\u8BED\u97F3\u64AD\u62A5" }),
8394
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-sub", children: "\u4EFB\u52A1\u5B8C\u6210 / \u505C\u6B62 / \u9700\u8981\u6388\u6743 / \u9700\u56DE\u7B54 / \u5361\u4F4F\u65F6\u7528\u6D4F\u89C8\u5668\u8BED\u97F3\uFF08TTS\uFF09\u8BF4\u4E00\u53E5\u8BDD\uFF1B\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF08\u8DE8\u6D4F\u89C8\u5668\uFF09\u4E0E\u672C\u673A\u5F00\u5173\uFF08\u5F53\u524D\u6D4F\u89C8\u5668\uFF09\u90FD\u5F00\u542F\u624D\u64AD\u62A5" }),
8395
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sec-sw", children: [
8396
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-swlabel" + (cfg.voiceNotify ? " on" : ""), children: cfg.voiceNotify ? "\u670D\u52A1\u7AEF\uFF1A\u5DF2\u5F00\u542F" : "\u670D\u52A1\u7AEF\uFF1A\u5DF2\u5173\u95ED" }),
8397
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8398
- "button",
8399
- {
8400
- type: "button",
8401
- className: "dock-sw" + (cfg.voiceNotify ? " on" : ""),
8402
- role: "switch",
8403
- "aria-checked": cfg.voiceNotify,
8404
- "aria-label": "\u5F00\u5173\u8BED\u97F3\u64AD\u62A5\uFF08\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF09",
8405
- title: cfg.voiceNotify ? "\u5173\u95ED\u8BED\u97F3\u64AD\u62A5\uFF08\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF09" : "\u5F00\u542F\u8BED\u97F3\u64AD\u62A5\uFF08\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF09",
8406
- onClick: () => patch({ voiceNotify: !cfg.voiceNotify })
8407
- }
8408
- )
8409
- ] })
8410
- ] }),
8411
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8412
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u672C\u673A\u64AD\u62A5" }),
8515
+ className: "dknt-seg-btn" + (source === "server" ? " on" : ""),
8516
+ "aria-pressed": source === "server",
8517
+ onClick: () => chooseSource("server"),
8518
+ children: "\u670D\u52A1\u7AEF\u914D\u7F6E"
8519
+ }
8520
+ ),
8413
8521
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8414
8522
  "button",
8415
8523
  {
8416
8524
  type: "button",
8417
- className: "dknt-miniswitch" + (voiceClientOn ? " on" : ""),
8418
- role: "switch",
8419
- "aria-checked": voiceClientOn,
8420
- "aria-label": "\u5F00\u5173\u672C\u673A\u8BED\u97F3\u64AD\u62A5",
8421
- title: voiceClientOn ? "\u5173\u95ED\u672C\u673A\u8BED\u97F3\u64AD\u62A5" : "\u5F00\u542F\u672C\u673A\u8BED\u97F3\u64AD\u62A5",
8422
- onClick: () => setVoiceClientOn(!voiceClientOn),
8423
- children: voiceClientOn ? "\u5F00" : "\u5173"
8525
+ className: "dknt-seg-btn" + (source === "client" ? " on" : ""),
8526
+ "aria-pressed": source === "client",
8527
+ onClick: () => chooseSource("client"),
8528
+ children: "\u672C\u673A\u914D\u7F6E"
8424
8529
  }
8425
- ),
8426
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: voiceClientOn ? "\u672C\u6D4F\u89C8\u5668\u4F1A\u64AD\u62A5\uFF08\u8BBE\u7F6E\u4FDD\u5B58\u5728\u5F53\u524D\u6D4F\u89C8\u5668\uFF1B\u670D\u52A1\u7AEF\u603B\u5F00\u5173\u5173\u95ED\u65F6\u4E0D\u751F\u6548\uFF09" : "\u672C\u6D4F\u89C8\u5668\u4E0D\u64AD\u62A5\uFF08\u8BBE\u7F6E\u4FDD\u5B58\u5728\u5F53\u524D\u6D4F\u89C8\u5668\uFF0C\u4E0D\u5F71\u54CD\u5176\u4ED6\u6D4F\u89C8\u5668\uFF09" })
8530
+ )
8427
8531
  ] }),
8428
- cfg.voiceNotify ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-rows-narrow", children: [
8429
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8430
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u64AD\u62A5\u53E3\u5F84" }),
8431
- [["brief", "\u7B80\u6D01"], ["medium", "\u9002\u4E2D"], ["detailed", "\u8BE6\u7EC6"]].map(([v, label]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8432
- "button",
8433
- {
8434
- type: "button",
8435
- className: "dknt-miniswitch" + (voiceTone(cfg) === v ? " on" : ""),
8436
- style: { marginRight: 6 },
8437
- title: "\u8BED\u97F3\u64AD\u62A5\u6309" + label + "\u6863\u8BF4",
8438
- onClick: () => patch({ voiceMode: v }),
8439
- children: label
8440
- },
8441
- v
8442
- )),
8443
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7B80\u6D01\uFF1A\u4E00\u53E5\u300C\u4EFB\u52A1\u5B8C\u6210 / \u4EFB\u52A1\u505C\u6B62\u4E86 / \u4EFB\u52A1\u9700\u8981\u6388\u6743 / \u4E3B\u4EFB\u52A1\uFF08\u6216\u5B50\u4EFB\u52A1\uFF09\xB7\u6807\u9898 \u5361\u4F4F\u4E86\u300D\uFF1B\u9002\u4E2D\uFF1A\u70B9\u540D\u4EFB\u52A1\uFF0C\u7ED3\u675F\u5E26\u539F\u56E0\u4E0E\u8017\u65F6\u3001\u5361\u4F4F\u5E26\u505C\u6EDE\u65F6\u957F\uFF1B\u8BE6\u7EC6\uFF1A\u7ED3\u675F\u5E26\u56DE\u5408\u7EDF\u8BA1\u4E0E\u56DE\u590D\u6458\u8981\uFF0C\u9700\u6388\u6743\u5E26\u5DE5\u5177\u540D\uFF0C\u5361\u4F4F\u5E26\u6700\u540E\u52A8\u4F5C" })
8444
- ] }),
8445
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8446
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u64AD\u62A5\u65F6\u523B" }),
8447
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", style: { minWidth: 0 }, children: [
8448
- ["voiceOnComplete", "\u5B8C\u6210", cfg.voiceOnComplete !== false],
8449
- ["voiceOnError", "\u505C\u6B62", cfg.voiceOnError !== false],
8450
- ["voiceOnConfirm", "\u9700\u6388\u6743/\u9700\u56DE\u7B54", cfg.voiceOnConfirm !== false],
8451
- ["voiceOnStuck", "\u5361\u4F4F", cfg.voiceOnStuck !== false]
8452
- ].map(([key, label, on]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8453
- "button",
8454
- {
8455
- type: "button",
8456
- className: "dknt-miniswitch" + (on ? " on" : ""),
8457
- style: { marginRight: 6 },
8458
- title: key === "voiceOnStuck" ? "\u7F16\u7A0B\u9636\u6BB5\u957F\u65F6\u95F4\u6CA1\u6709\u52A8\u9759\u65F6\u64AD\u62A5\u4E00\u6B21\uFF08\u6062\u590D\u540E\u53EF\u518D\u62A5\uFF1B\u547D\u4EE4\u5728\u8DD1 / \u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587\u4E0D\u7B97\uFF09" : "",
8459
- onClick: () => patch({ [key]: !on }),
8460
- children: [
8461
- label,
8462
- on ? "\xB7\u5F00" : "\xB7\u5173"
8463
- ]
8464
- },
8465
- key
8466
- )) })
8467
- ] }),
8468
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8469
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8BED\u901F" }),
8470
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8471
- "input",
8472
- {
8473
- type: "range",
8474
- min: "0.5",
8475
- max: "2",
8476
- step: "0.05",
8477
- value: String(cfg.voiceRate || 1),
8478
- "aria-label": "\u64AD\u62A5\u8BED\u901F",
8479
- style: { width: 120, accentColor: "var(--dk-accent)" },
8480
- onChange: (e) => patch({ voiceRate: Number(e.target.value) || 1 })
8481
- }
8482
- ),
8483
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub", children: [
8484
- Number(cfg.voiceRate || 1).toFixed(2),
8485
- "\xD7\uFF08\u64AD\u62A5\u6BD4\u6B63\u6587\u6717\u8BFB\u7565\u5FEB\u66F4\u5229\u843D\uFF09"
8486
- ] })
8532
+ source === "client" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dknt-btn", onClick: copyFromServer, children: "\u4ECE\u670D\u52A1\u7AEF\u590D\u5236" }) : null
8533
+ ] }, "source"),
8534
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-tabs", role: "tablist", "aria-label": "\u4EFB\u52A1\u901A\u77E5\u8BBE\u7F6E", children: [
8535
+ ["events", "\u6309\u4E8B\u4EF6\u63D0\u9192"],
8536
+ ["channels", "\u6309\u6E20\u9053\u8BBE\u7F6E"],
8537
+ ["robots", "\u7FA4\u673A\u5668\u4EBA"]
8538
+ ].map(([id, label]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8539
+ "button",
8540
+ {
8541
+ type: "button",
8542
+ role: "tab",
8543
+ "aria-selected": tab === id,
8544
+ className: "dknt-tab" + (tab === id ? " on" : ""),
8545
+ onClick: () => setTab(id),
8546
+ children: label
8547
+ },
8548
+ id
8549
+ )) }, "tabs")
8550
+ );
8551
+ if (tab === "events") {
8552
+ rows.push(
8553
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec", children: [
8554
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec-head", children: [
8555
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-title", children: "\u901A\u77E5\u4E8B\u4EF6" }),
8556
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-sub", children: "\u7EB5\u5411\u662F\u901A\u77E5\u4E8B\u4EF6\u3001\u6A2A\u5411\u662F\u901A\u77E5\u6E20\u9053\uFF1B\u52FE\u9009\u8868\u793A\u300C\u8FD9\u4E2A\u4E8B\u4EF6\u7528\u8FD9\u4E2A\u6E20\u9053\u63D0\u9192\u300D\u3002\u6E20\u9053\u7684\u603B\u5F00\u5173\u548C\u8BE6\u7EC6\u8BBE\u7F6E\u5728\u540C\u9875\u300C\u6309\u6E20\u9053\u8BBE\u7F6E\u300D\u3002" })
8487
8557
  ] }),
8488
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8489
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u97F3\u91CF" }),
8490
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8491
- "input",
8492
- {
8493
- type: "range",
8494
- min: "0",
8495
- max: "1",
8496
- step: "0.05",
8497
- value: String(cfg.voiceVolume == null ? 1 : cfg.voiceVolume),
8498
- "aria-label": "\u64AD\u62A5\u97F3\u91CF",
8499
- style: { width: 120, accentColor: "var(--dk-accent)" },
8500
- onChange: (e) => patch({ voiceVolume: Number(e.target.value) })
8501
- }
8502
- ),
8503
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub", children: [
8504
- Math.round((cfg.voiceVolume == null ? 1 : cfg.voiceVolume) * 100),
8505
- "%"
8558
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EventMatrix, { cfg, source, voiceClientOn, patch }),
8559
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u300C\u9700\u786E\u8BA4 / \u9700\u56DE\u7B54\u300D\u5305\u542B\u5DE5\u5177\u7B49\u5F85\u6279\u51C6\u4E0E\u4F1A\u8BDD\u63D0\u95EE\u7B49\u5F85\u56DE\u7B54\u4E24\u79CD\u300C\u505C\u5728\u539F\u5730\u7B49\u4EBA\u300D\uFF1B\u300C\u5361\u4F4F\u300D\u53EA\u5728\u7F16\u7A0B\u9636\u6BB5\u957F\u65F6\u95F4\u6CA1\u6709\u52A8\u9759\u65F6\u89E6\u53D1\uFF0C\u7B49\u6279\u51C6\u3001\u7B49\u56DE\u7B54\u3001\u547D\u4EE4\u5728\u8DD1\u3001\u6B63\u5728\u538B\u7F29\u4E0A\u4E0B\u6587\u90FD\u4E0D\u7B97\u5361\u4F4F\u3002" })
8560
+ ] }, "events")
8561
+ );
8562
+ } else if (tab === "channels") {
8563
+ rows.push(
8564
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channels", children: [
8565
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel", children: [
8566
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-head", children: [
8567
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-title-wrap", children: [
8568
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-title", children: "\u9875\u5185\u5361\u7247" }),
8569
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-sub", children: "\u53F3\u4FA7\u6D6E\u5C42\u901A\u77E5\u5361\uFF1B\u70B9\u5361\u7247\u76F4\u8FBE\u5BF9\u5E94\u4F1A\u8BDD" })
8570
+ ] }),
8571
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8572
+ "button",
8573
+ {
8574
+ type: "button",
8575
+ className: "dock-sw" + (cfg.notifyCards !== false ? " on" : ""),
8576
+ role: "switch",
8577
+ "aria-checked": cfg.notifyCards !== false,
8578
+ "aria-label": "\u5F00\u5173\u9875\u5185\u5361\u7247",
8579
+ onClick: () => patch({ notifyCards: cfg.notifyCards === false })
8580
+ }
8581
+ )
8582
+ ] }),
8583
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-body", children: [
8584
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8585
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u6B63\u6587\u53E3\u5F84" }),
8586
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModePicker, { value: cardTone(cfg), title: "\u9875\u5185\u5361\u7247\u6B63\u6587", onChange: (v) => patch({ cardMode: v }) }),
8587
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7B80\u6D01\uFF1D\u4EFB\u52A1\u4E0E\u8017\u65F6 / \u8C01\u5361\u4F4F\uFF1B\u9002\u4E2D\uFF1D\u52A0\u6A21\u578B\u3001\u8D77\u6B62\u65F6\u95F4\u3001\u505C\u6EDE\u65F6\u957F\uFF1B\u8BE6\u7EC6\uFF1D\u5168\u90E8\uFF08\u56DE\u5408\u6B65\u9AA4\u3001Token\u3001\u6458\u8981\u6216\u9519\u8BEF\u3001\u6700\u540E\u52A8\u4F5C\uFF09" })
8588
+ ] }),
8589
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8590
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u5361\u7247\u6536\u7EB3" }),
8591
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u6240\u6709\u5361\u7247\u90FD\u4E0D\u8D85\u65F6\u81EA\u52A8\u6D88\u5931\uFF1A\u7ED3\u675F\u5361\u6CA1\u770B\u8FC7\u5C31\u4E00\u76F4\u6302\u7740\uFF0C\u70B9\u5361\u7247\u6216\u70B9\u8FDB\u4F1A\u8BDD\u540E\u6536\u8D77\uFF1B\u9700\u786E\u8BA4\u5361\u6302\u5230\u5904\u7406\u5B8C\uFF1B\u5361\u4F4F\u5361\u6302\u5230\u6062\u590D\u6D3B\u52A8\u30023 \u5F20\u53CA\u4EE5\u4E0A\u81EA\u52A8\u53E0\u653E\u6210\u6807\u9898\u6761\uFF0C\u9F20\u6807\u79FB\u4E0A\u53BB\u6574\u4F53\u5C55\u5F00\u3002" })
8592
+ ] }),
8593
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8594
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u4E8B\u4EF6\u8303\u56F4" }),
8595
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u5728\u300C\u6309\u4E8B\u4EF6\u63D0\u9192\u300D\u7684\u9875\u5185\u5361\u7247\u5217\u91CC\u52FE\u9009\u3002" })
8596
+ ] })
8506
8597
  ] })
8507
8598
  ] }),
8508
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8509
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u97F3\u8272" }),
8510
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8511
- "select",
8512
- {
8513
- className: "dknt-input",
8514
- style: { maxWidth: 260 },
8515
- value: cfg.voiceURI || "",
8516
- "aria-label": "\u64AD\u62A5\u97F3\u8272",
8517
- onChange: (e) => patch({ voiceURI: e.target.value }),
8518
- children: [
8519
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "\u81EA\u52A8\uFF08\u6309\u8BED\u8A00\u6311\uFF09" }),
8520
- (() => {
8521
- const zh = [], other = [];
8522
- for (const v of voices) {
8523
- if (!v || !v.voiceURI) continue;
8524
- if (/^zh/i.test(String(v.lang || ""))) zh.push(v);
8525
- else other.push(v);
8526
- }
8527
- const groups = [];
8528
- if (zh.length) groups.push(["\u4E2D\u6587\u97F3\u8272", zh]);
8529
- if (other.length) groups.push(["\u5176\u4ED6\u97F3\u8272", other]);
8530
- return groups.map(([gname, vs]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("optgroup", { label: gname, children: vs.map((v) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: v.voiceURI, children: (v.name || v.voiceURI) + "\uFF08" + (v.lang || "?") + "\uFF09" }, v.voiceURI)) }, gname));
8531
- })()
8532
- ]
8533
- }
8534
- ),
8535
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: voices.length ? "\u97F3\u8272\u662F\u672C\u673A\u6D4F\u89C8\u5668\u7ED9\u7684\uFF0C\u6362\u8BBE\u5907\u53EF\u80FD\u8981\u91CD\u9009\uFF1B\u672C\u673A\u627E\u4E0D\u5230\u6240\u9009\u97F3\u8272\u65F6\u81EA\u52A8\u6309\u8BED\u8A00\u56DE\u843D" : "\u672C\u673A\u6682\u672A\u8BFB\u5230\u97F3\u8272\uFF08\u7CFB\u7EDF\u8BED\u97F3\u672A\u88C5/\u672A\u542F\u7528\uFF09\uFF0C\u5C06\u6309\u8BED\u8A00\u81EA\u52A8\u6311" })
8536
- ] }),
8537
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8538
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8BD5\u542C" }),
8539
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8540
- "button",
8541
- {
8542
- type: "button",
8543
- className: "dknt-btn",
8544
- disabled: !voiceSupported(),
8545
- onClick: () => {
8546
- const preview = Object.assign({}, cfg, { voiceNotify: true });
8547
- speakVoice(endBroadcastText(true, { title: "\u793A\u4F8B\u4EFB\u52A1", duration: 125e3, turns: 3, steps: 9, toolCalls: 4, lastText: "\u597D\u7684\uFF0C\u4E09\u4EFD\u6587\u6863\u90FD\u5DF2\u66F4\u65B0\u5B8C\u6BD5\u3002" }, null, preview), preview);
8548
- },
8549
- children: "\u64AD\u4E00\u53E5"
8550
- }
8551
- ),
8552
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8553
- "button",
8554
- {
8555
- type: "button",
8556
- className: "dknt-btn",
8557
- disabled: !voiceSupported(),
8558
- onClick: () => {
8559
- const preview = Object.assign({}, cfg, { voiceNotify: true });
8560
- speakVoice(confirmBroadcastText({ title: "\u793A\u4F8B\u4EFB\u52A1" }, { toolName: "pwsh" }, preview), preview);
8599
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel", children: [
8600
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-head", children: [
8601
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-title-wrap", children: [
8602
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-title", children: "\u63D0\u793A\u97F3" }),
8603
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-sub", children: "\u4EFB\u52A1\u7ED3\u675F / \u9700\u786E\u8BA4\u65F6\u64AD\u653E\uFF0C6 \u79CD\u97F3\u6548\u53EF\u9009" })
8604
+ ] }),
8605
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8606
+ "button",
8607
+ {
8608
+ type: "button",
8609
+ className: "dock-sw" + (cfg.soundNotify !== false ? " on" : ""),
8610
+ role: "switch",
8611
+ "aria-checked": cfg.soundNotify !== false,
8612
+ "aria-label": "\u5F00\u5173\u63D0\u793A\u97F3",
8613
+ onClick: () => patch({ soundNotify: cfg.soundNotify === false })
8614
+ }
8615
+ )
8616
+ ] }),
8617
+ cfg.soundNotify !== false ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-body", children: [
8618
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-sounds", children: Object.keys(SOUND_LIBRARY).map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8619
+ "button",
8620
+ {
8621
+ type: "button",
8622
+ className: "dknt-sound" + (cfg.soundEffect === key ? " on" : ""),
8623
+ onClick: () => patch({ soundEffect: key }),
8624
+ children: [
8625
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sound-name", children: [
8626
+ SOUND_LIBRARY[key].name,
8627
+ cfg.soundEffect === key ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sound-cur", children: "\u2713" }) : null
8628
+ ] }),
8629
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8630
+ "span",
8631
+ {
8632
+ className: "dknt-sound-play",
8633
+ role: "button",
8634
+ tabIndex: 0,
8635
+ title: "\u8BD5\u542C " + SOUND_LIBRARY[key].name,
8636
+ onClick: (e) => {
8637
+ e.stopPropagation();
8638
+ previewSound(key);
8639
+ },
8640
+ onKeyDown: (e) => {
8641
+ if (e.key === "Enter" || e.key === " ") {
8642
+ e.preventDefault();
8643
+ e.stopPropagation();
8644
+ previewSound(key);
8645
+ }
8646
+ },
8647
+ children: "\u25B6"
8648
+ }
8649
+ )
8650
+ ]
8561
8651
  },
8562
- children: "\u9700\u6388\u6743"
8563
- }
8564
- ),
8565
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: voiceSupported() ? "\u6D4F\u89C8\u5668\u8BED\u97F3\u5408\u6210\uFF08\u4E0E\u3010\u8BED\u97F3\u6717\u8BFB\u3011\u540C\u4E00\u5957\u58F0\u97F3\uFF0C\u72EC\u7ACB\u5F00\u5173\uFF1B\u6253\u65AD\u5F0F\u2014\u2014\u64AD\u62A5\u4FE1\u65F6\u6B63\u5728\u6717\u8BFB\u7684\u6B63\u6587\u4F1A\u8BA9\u4F4D\uFF09" : "\u672C\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u8BED\u97F3\u5408\u6210\uFF08speechSynthesis \u4E0D\u53EF\u7528\uFF09" })
8652
+ key
8653
+ )) }),
8654
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8655
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u4E8B\u4EF6\u8303\u56F4" }),
8656
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u5728\u300C\u6309\u4E8B\u4EF6\u63D0\u9192\u300D\u7684\u63D0\u793A\u97F3\u5217\u91CC\u52FE\u9009\uFF08\u652F\u6301\u5B8C\u6210 / \u5F02\u5E38 / \u9700\u786E\u8BA4\uFF1B\u5361\u4F4F\u6CA1\u6709\u63D0\u793A\u97F3\uFF09\u3002" })
8657
+ ] })
8658
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-channel-off", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u4E8B\u4EF6\u4E0D\u64AD\u653E\u63D0\u793A\u97F3\u3002" })
8566
8659
  ] }),
8567
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8568
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8BED\u8A00" }),
8569
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8570
- "select",
8571
- {
8572
- className: "dknt-input",
8573
- style: { maxWidth: 180 },
8574
- value: cfg.voiceLang || "",
8575
- "aria-label": "\u64AD\u62A5\u8BED\u8A00",
8576
- onChange: (e) => patch({ voiceLang: e.target.value }),
8577
- children: [
8578
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "\u81EA\u52A8\uFF08\u4E2D\u6587\u4F18\u5148\uFF09" }),
8579
- ["zh-CN", "zh-TW", "en-US", "en-GB", "ja-JP", "ko-KR"].map((l) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: l, children: l }, l))
8580
- ]
8581
- }
8582
- ),
8583
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u672A\u6307\u5B9A\u97F3\u8272\u65F6\u6309\u8BED\u8A00\u81EA\u52A8\u6311\uFF1B\u5DF2\u9009\u97F3\u8272\u7684\u8BED\u8A00\u4F1A\u8986\u76D6\u8FD9\u91CC" })
8584
- ] })
8585
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u670D\u52A1\u7AEF\u603B\u5F00\u5173\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u4E8B\u4EF6\u4E0D\u64AD\u62A5\u8BED\u97F3\uFF08\u63D0\u793A\u97F3\u3001\u7CFB\u7EDF\u901A\u77E5\u4E0D\u53D7\u5F71\u54CD\uFF09\uFF1B\u4E0A\u9762\u7684\u300C\u672C\u673A\u64AD\u62A5\u300D\u53EA\u51B3\u5B9A\u672C\u6D4F\u89C8\u5668\u662F\u5426\u51FA\u58F0\u3002" })
8586
- ] }, "voice"),
8587
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec", children: [
8588
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec-head", children: [
8589
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-title", children: "\u9489\u9489\u63A8\u9001" }),
8590
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u9489\u9489\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
8591
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sec-sw", children: [
8592
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-swlabel" + (cfg.dingtalkEnabled ? " on" : ""), children: cfg.dingtalkEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
8593
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8594
- "button",
8595
- {
8596
- type: "button",
8597
- className: "dock-sw" + (cfg.dingtalkEnabled ? " on" : ""),
8598
- role: "switch",
8599
- "aria-checked": cfg.dingtalkEnabled,
8600
- "aria-label": "\u5F00\u5173\u9489\u9489\u63A8\u9001",
8601
- title: cfg.dingtalkEnabled ? "\u5173\u95ED\u9489\u9489\u63A8\u9001" : "\u5F00\u542F\u9489\u9489\u63A8\u9001",
8602
- onClick: () => patch({ dingtalkEnabled: !cfg.dingtalkEnabled })
8603
- }
8604
- )
8605
- ] })
8606
- ] }),
8607
- cfg.dingtalkEnabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-rows-narrow", children: [
8608
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row dknt-row-webhook", children: [
8609
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "Webhook" }),
8610
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8611
- "input",
8612
- {
8613
- type: "text",
8614
- className: "dknt-input",
8615
- spellCheck: false,
8616
- value: cfg.dingtalkWebhook || "",
8617
- placeholder: "https://oapi.dingtalk.com/robot/send?access_token=\u2026",
8618
- onChange: (e) => {
8619
- editingWebhookRef.current = true;
8620
- setCfg(Object.assign({}, cfg, { dingtalkWebhook: e.target.value }));
8660
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel", children: [
8661
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-head", children: [
8662
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-title-wrap", children: [
8663
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-title", children: "\u7CFB\u7EDF\u901A\u77E5" }),
8664
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-sub", children: "\u6D4F\u89C8\u5668\u7CFB\u7EDF\u901A\u77E5\uFF0C\u4EC5\u9875\u9762\u5728\u540E\u53F0\u65F6\u63A8\u9001" })
8665
+ ] }),
8666
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8667
+ "button",
8668
+ {
8669
+ type: "button",
8670
+ className: "dock-sw" + (cfg.systemNotify ? " on" : ""),
8671
+ role: "switch",
8672
+ "aria-checked": cfg.systemNotify,
8673
+ "aria-label": "\u5F00\u5173\u7CFB\u7EDF\u901A\u77E5",
8674
+ onClick: () => enableSystemNotify(!cfg.systemNotify)
8621
8675
  }
8622
- }
8623
- ),
8624
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8625
- "button",
8626
- {
8627
- type: "button",
8628
- className: "dknt-btn",
8629
- disabled: !editingWebhookRef.current,
8630
- onClick: saveWebhook,
8631
- children: editingWebhookRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
8632
- }
8633
- )
8634
- ] }),
8635
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8636
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
8637
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dknt-btn", disabled: testing, onClick: runDingtalkTest, children: testing ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
8638
- testState ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub" + (testState.ok ? " dknt-ok" : " dknt-err"), children: [
8639
- testState.ok ? "\u2713 " : "\u2717 ",
8640
- testState.msg
8641
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
8676
+ )
8677
+ ] }),
8678
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-body", children: [
8679
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8680
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u6743\u9650" }),
8681
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: permNote })
8682
+ ] }),
8683
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8684
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u4E8B\u4EF6\u8303\u56F4" }),
8685
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u5728\u300C\u6309\u4E8B\u4EF6\u63D0\u9192\u300D\u7684\u7CFB\u7EDF\u901A\u77E5\u5217\u91CC\u52FE\u9009\uFF08\u652F\u6301\u5B8C\u6210 / \u5F02\u5E38 / \u9700\u786E\u8BA4\uFF1B\u5361\u4F4F\u6CA1\u6709\u7CFB\u7EDF\u901A\u77E5\uFF09\u3002" })
8686
+ ] })
8687
+ ] })
8642
8688
  ] }),
8643
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u9489\u9489\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u667A\u80FD\u7FA4\u52A9\u624B \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\uFF08Webhook\uFF09\uFF0C \u5B89\u5168\u8BBE\u7F6E\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
8644
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u9489\u9489\u3002" })
8645
- ] }, "dingtalk"),
8646
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec", children: [
8647
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-sec-head", children: [
8648
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-title", children: "\u98DE\u4E66\u63A8\u9001" }),
8649
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u98DE\u4E66\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
8650
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sec-sw", children: [
8651
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-swlabel" + (cfg.feishuEnabled ? " on" : ""), children: cfg.feishuEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
8652
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8653
- "button",
8654
- {
8655
- type: "button",
8656
- className: "dock-sw" + (cfg.feishuEnabled ? " on" : ""),
8657
- role: "switch",
8658
- "aria-checked": cfg.feishuEnabled,
8659
- "aria-label": "\u5F00\u5173\u98DE\u4E66\u63A8\u9001",
8660
- title: cfg.feishuEnabled ? "\u5173\u95ED\u98DE\u4E66\u63A8\u9001" : "\u5F00\u542F\u98DE\u4E66\u63A8\u9001",
8661
- onClick: () => patch({ feishuEnabled: !cfg.feishuEnabled })
8662
- }
8663
- )
8689
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel", children: [
8690
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-head", children: [
8691
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-title-wrap", children: [
8692
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-title", children: "\u8BED\u97F3\u64AD\u62A5" }),
8693
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-sub", children: "\u7528\u6D4F\u89C8\u5668\u8BED\u97F3\uFF08TTS\uFF09\u8BF4\u4E00\u53E5\u8BDD\uFF1B\u670D\u52A1\u7AEF\u603B\u5F00\u5173 + \u672C\u673A\u5F00\u5173\u90FD\u5F00\u624D\u64AD\u62A5" })
8694
+ ] }),
8695
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sec-sw", children: [
8696
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-swlabel" + (cfg.voiceNotify ? " on" : ""), children: cfg.voiceNotify ? "\u670D\u52A1\u7AEF\uFF1A\u5DF2\u5F00\u542F" : "\u670D\u52A1\u7AEF\uFF1A\u5DF2\u5173\u95ED" }),
8697
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8698
+ "button",
8699
+ {
8700
+ type: "button",
8701
+ className: "dock-sw" + (cfg.voiceNotify ? " on" : ""),
8702
+ role: "switch",
8703
+ "aria-checked": cfg.voiceNotify,
8704
+ "aria-label": "\u5F00\u5173\u8BED\u97F3\u64AD\u62A5\uFF08\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF09",
8705
+ disabled: source === "client",
8706
+ title: source === "client" ? "\u670D\u52A1\u7AEF\u603B\u5F00\u5173\u9700\u5207\u6362\u5230\u300C\u670D\u52A1\u7AEF\u914D\u7F6E\u300D\u4FEE\u6539" : cfg.voiceNotify ? "\u5173\u95ED\u8BED\u97F3\u64AD\u62A5\uFF08\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF09" : "\u5F00\u542F\u8BED\u97F3\u64AD\u62A5\uFF08\u670D\u52A1\u7AEF\u603B\u5F00\u5173\uFF09",
8707
+ onClick: () => {
8708
+ if (source !== "client") patch({ voiceNotify: !cfg.voiceNotify });
8709
+ }
8710
+ }
8711
+ )
8712
+ ] })
8713
+ ] }),
8714
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-body", children: [
8715
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8716
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u672C\u673A\u64AD\u62A5" }),
8717
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8718
+ "button",
8719
+ {
8720
+ type: "button",
8721
+ className: "dknt-miniswitch" + (voiceClientOn ? " on" : ""),
8722
+ role: "switch",
8723
+ "aria-checked": voiceClientOn,
8724
+ "aria-label": "\u5F00\u5173\u672C\u673A\u8BED\u97F3\u64AD\u62A5",
8725
+ title: voiceClientOn ? "\u5173\u95ED\u672C\u673A\u8BED\u97F3\u64AD\u62A5" : "\u5F00\u542F\u672C\u673A\u8BED\u97F3\u64AD\u62A5",
8726
+ onClick: () => setVoiceClientOn(!voiceClientOn),
8727
+ children: voiceClientOn ? "\u5F00" : "\u5173"
8728
+ }
8729
+ ),
8730
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: voiceClientOn ? "\u672C\u6D4F\u89C8\u5668\u4F1A\u64AD\u62A5\uFF08\u8BBE\u7F6E\u4FDD\u5B58\u5728\u5F53\u524D\u6D4F\u89C8\u5668\uFF1B\u670D\u52A1\u7AEF\u603B\u5F00\u5173\u5173\u95ED\u65F6\u4E0D\u751F\u6548\uFF09" : "\u672C\u6D4F\u89C8\u5668\u4E0D\u64AD\u62A5\uFF08\u8BBE\u7F6E\u4FDD\u5B58\u5728\u5F53\u524D\u6D4F\u89C8\u5668\uFF0C\u4E0D\u5F71\u54CD\u5176\u4ED6\u6D4F\u89C8\u5668\uFF09" })
8731
+ ] }),
8732
+ cfg.voiceNotify ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
8733
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8734
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u64AD\u62A5\u53E3\u5F84" }),
8735
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModePicker, { value: voiceTone(cfg), title: "\u8BED\u97F3\u64AD\u62A5", onChange: (v) => patch({ voiceMode: v }) }),
8736
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7B80\u6D01\uFF1A\u4E00\u53E5\u300C\u4EFB\u52A1\u5B8C\u6210 / \u4EFB\u52A1\u505C\u6B62\u4E86 / \u4EFB\u52A1\u9700\u8981\u6388\u6743 / \u4E3B\u4EFB\u52A1\uFF08\u6216\u5B50\u4EFB\u52A1\uFF09\xB7\u6807\u9898 \u5361\u4F4F\u4E86\u300D\uFF1B\u9002\u4E2D\uFF1A\u70B9\u540D\u4EFB\u52A1\uFF0C\u7ED3\u675F\u5E26\u539F\u56E0\u4E0E\u8017\u65F6\u3001\u5361\u4F4F\u5E26\u505C\u6EDE\u65F6\u957F\uFF1B\u8BE6\u7EC6\uFF1A\u7ED3\u675F\u5E26\u56DE\u5408\u7EDF\u8BA1\u4E0E\u56DE\u590D\u6458\u8981\uFF0C\u9700\u6388\u6743\u5E26\u5DE5\u5177\u540D\uFF0C\u5361\u4F4F\u5E26\u6700\u540E\u52A8\u4F5C\u3002" })
8737
+ ] }),
8738
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8739
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u64AD\u62A5\u4E8B\u4EF6" }),
8740
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u5728\u300C\u6309\u4E8B\u4EF6\u63D0\u9192\u300D\u7684\u8BED\u97F3\u64AD\u62A5\u5217\u91CC\u52FE\u9009\uFF08\u652F\u6301\u5B8C\u6210 / \u5F02\u5E38 / \u9700\u786E\u8BA4 / \u5361\u4F4F\uFF09\u3002" })
8741
+ ] }),
8742
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8743
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8BED\u901F" }),
8744
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8745
+ "input",
8746
+ {
8747
+ type: "range",
8748
+ min: "0.5",
8749
+ max: "2",
8750
+ step: "0.05",
8751
+ value: String(cfg.voiceRate || 1),
8752
+ "aria-label": "\u64AD\u62A5\u8BED\u901F",
8753
+ style: { width: 120, accentColor: "var(--dk-accent)" },
8754
+ onChange: (e) => patch({ voiceRate: Number(e.target.value) || 1 })
8755
+ }
8756
+ ),
8757
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub", children: [
8758
+ Number(cfg.voiceRate || 1).toFixed(2),
8759
+ "\xD7\uFF08\u64AD\u62A5\u6BD4\u6B63\u6587\u6717\u8BFB\u7565\u5FEB\u66F4\u5229\u843D\uFF09"
8760
+ ] })
8761
+ ] }),
8762
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8763
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u97F3\u91CF" }),
8764
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8765
+ "input",
8766
+ {
8767
+ type: "range",
8768
+ min: "0",
8769
+ max: "1",
8770
+ step: "0.05",
8771
+ value: String(cfg.voiceVolume == null ? 1 : cfg.voiceVolume),
8772
+ "aria-label": "\u64AD\u62A5\u97F3\u91CF",
8773
+ style: { width: 120, accentColor: "var(--dk-accent)" },
8774
+ onChange: (e) => patch({ voiceVolume: Number(e.target.value) })
8775
+ }
8776
+ ),
8777
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub", children: [
8778
+ Math.round((cfg.voiceVolume == null ? 1 : cfg.voiceVolume) * 100),
8779
+ "%"
8780
+ ] })
8781
+ ] }),
8782
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8783
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u97F3\u8272" }),
8784
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8785
+ "select",
8786
+ {
8787
+ className: "dknt-input",
8788
+ style: { maxWidth: 260 },
8789
+ value: cfg.voiceURI || "",
8790
+ "aria-label": "\u64AD\u62A5\u97F3\u8272",
8791
+ onChange: (e) => patch({ voiceURI: e.target.value }),
8792
+ children: [
8793
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "\u81EA\u52A8\uFF08\u6309\u8BED\u8A00\u6311\uFF09" }),
8794
+ (() => {
8795
+ const zh = [], other = [];
8796
+ for (const v of voices) {
8797
+ if (!v || !v.voiceURI) continue;
8798
+ if (/^zh/i.test(String(v.lang || ""))) zh.push(v);
8799
+ else other.push(v);
8800
+ }
8801
+ const groups = [];
8802
+ if (zh.length) groups.push(["\u4E2D\u6587\u97F3\u8272", zh]);
8803
+ if (other.length) groups.push(["\u5176\u4ED6\u97F3\u8272", other]);
8804
+ return groups.map(([gname, vs]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("optgroup", { label: gname, children: vs.map((v) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: v.voiceURI, children: (v.name || v.voiceURI) + "\uFF08" + (v.lang || "?") + "\uFF09" }, v.voiceURI)) }, gname));
8805
+ })()
8806
+ ]
8807
+ }
8808
+ ),
8809
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: voices.length ? "\u97F3\u8272\u662F\u672C\u673A\u6D4F\u89C8\u5668\u7ED9\u7684\uFF0C\u6362\u8BBE\u5907\u53EF\u80FD\u8981\u91CD\u9009\uFF1B\u672C\u673A\u627E\u4E0D\u5230\u6240\u9009\u97F3\u8272\u65F6\u81EA\u52A8\u6309\u8BED\u8A00\u56DE\u843D" : "\u672C\u673A\u6682\u672A\u8BFB\u5230\u97F3\u8272\uFF08\u7CFB\u7EDF\u8BED\u97F3\u672A\u88C5/\u672A\u542F\u7528\uFF09\uFF0C\u5C06\u6309\u8BED\u8A00\u81EA\u52A8\u6311" })
8810
+ ] }),
8811
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8812
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8BD5\u542C" }),
8813
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8814
+ "button",
8815
+ {
8816
+ type: "button",
8817
+ className: "dknt-btn",
8818
+ disabled: !voiceSupported(),
8819
+ onClick: () => {
8820
+ const preview = Object.assign({}, cfg, { voiceNotify: true });
8821
+ speakVoice(endBroadcastText(true, { title: "\u793A\u4F8B\u4EFB\u52A1", duration: 125e3, turns: 3, steps: 9, toolCalls: 4, lastText: "\u597D\u7684\uFF0C\u4E09\u4EFD\u6587\u6863\u90FD\u5DF2\u66F4\u65B0\u5B8C\u6BD5\u3002" }, null, preview), preview);
8822
+ },
8823
+ children: "\u64AD\u4E00\u53E5"
8824
+ }
8825
+ ),
8826
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8827
+ "button",
8828
+ {
8829
+ type: "button",
8830
+ className: "dknt-btn",
8831
+ disabled: !voiceSupported(),
8832
+ onClick: () => {
8833
+ const preview = Object.assign({}, cfg, { voiceNotify: true });
8834
+ speakVoice(confirmBroadcastText({ title: "\u793A\u4F8B\u4EFB\u52A1" }, { toolName: "pwsh" }, preview), preview);
8835
+ },
8836
+ children: "\u9700\u6388\u6743"
8837
+ }
8838
+ ),
8839
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: voiceSupported() ? "\u6D4F\u89C8\u5668\u8BED\u97F3\u5408\u6210\uFF08\u4E0E\u3010\u8BED\u97F3\u6717\u8BFB\u3011\u540C\u4E00\u5957\u58F0\u97F3\uFF0C\u72EC\u7ACB\u5F00\u5173\uFF1B\u6253\u65AD\u5F0F\u2014\u2014\u64AD\u62A5\u4FE1\u65F6\u6B63\u5728\u6717\u8BFB\u7684\u6B63\u6587\u4F1A\u8BA9\u4F4D\uFF09" : "\u672C\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u8BED\u97F3\u5408\u6210\uFF08speechSynthesis \u4E0D\u53EF\u7528\uFF09" })
8840
+ ] }),
8841
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8842
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8BED\u8A00" }),
8843
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
8844
+ "select",
8845
+ {
8846
+ className: "dknt-input",
8847
+ style: { maxWidth: 180 },
8848
+ value: cfg.voiceLang || "",
8849
+ "aria-label": "\u64AD\u62A5\u8BED\u8A00",
8850
+ onChange: (e) => patch({ voiceLang: e.target.value }),
8851
+ children: [
8852
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "\u81EA\u52A8\uFF08\u4E2D\u6587\u4F18\u5148\uFF09" }),
8853
+ ["zh-CN", "zh-TW", "en-US", "en-GB", "ja-JP", "ko-KR"].map((l) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: l, children: l }, l))
8854
+ ]
8855
+ }
8856
+ ),
8857
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u672A\u6307\u5B9A\u97F3\u8272\u65F6\u6309\u8BED\u8A00\u81EA\u52A8\u6311\uFF1B\u5DF2\u9009\u97F3\u8272\u7684\u8BED\u8A00\u4F1A\u8986\u76D6\u8FD9\u91CC" })
8858
+ ] })
8859
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-channel-off", children: "\u670D\u52A1\u7AEF\u603B\u5F00\u5173\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u4E8B\u4EF6\u4E0D\u64AD\u62A5\u8BED\u97F3\uFF1B\u4E0A\u9762\u7684\u300C\u672C\u673A\u64AD\u62A5\u300D\u53EA\u51B3\u5B9A\u672C\u6D4F\u89C8\u5668\u662F\u5426\u51FA\u58F0\u3002" })
8860
+ ] })
8664
8861
  ] })
8665
- ] }),
8666
- cfg.feishuEnabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-rows-narrow", children: [
8667
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row dknt-row-webhook", children: [
8668
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "Webhook" }),
8669
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8670
- "input",
8671
- {
8672
- type: "text",
8673
- className: "dknt-input",
8674
- spellCheck: false,
8675
- value: cfg.feishuWebhook || "",
8676
- placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026",
8677
- onChange: (e) => {
8678
- editingFeishuRef.current = true;
8679
- setCfg(Object.assign({}, cfg, { feishuWebhook: e.target.value }));
8680
- }
8681
- }
8682
- ),
8683
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8684
- "button",
8685
- {
8686
- type: "button",
8687
- className: "dknt-btn",
8688
- disabled: !editingFeishuRef.current,
8689
- onClick: saveFeishuWebhook,
8690
- children: editingFeishuRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
8691
- }
8692
- )
8693
- ] }),
8694
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8695
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
8696
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dknt-btn", disabled: feishuTesting, onClick: runFeishuTest, children: feishuTesting ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
8697
- feishuTestState ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub" + (feishuTestState.ok ? " dknt-ok" : " dknt-err"), children: [
8698
- feishuTestState.ok ? "\u2713 " : "\u2717 ",
8699
- feishuTestState.msg
8700
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
8862
+ ] }, "channels")
8863
+ );
8864
+ } else {
8865
+ rows.push(
8866
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channels", children: [
8867
+ source === "client" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note dknt-note-box", children: "\u7FA4\u673A\u5668\u4EBA\u63A8\u9001\u7531\u670D\u52A1\u7AEF\u6267\u884C\uFF0C\u59CB\u7EC8\u4F7F\u7528\u670D\u52A1\u7AEF\u914D\u7F6E\uFF1B\u8BF7\u5207\u6362\u5230\u300C\u670D\u52A1\u7AEF\u914D\u7F6E\u300D\u4FEE\u6539\u3002" }) : null,
8868
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel", children: [
8869
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-head", children: [
8870
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-title-wrap", children: [
8871
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-title", children: "\u9489\u9489\u63A8\u9001" }),
8872
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u9489\u9489\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF09" })
8873
+ ] }),
8874
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sec-sw", children: [
8875
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-swlabel" + (cfg.dingtalkEnabled ? " on" : ""), children: cfg.dingtalkEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
8876
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8877
+ "button",
8878
+ {
8879
+ type: "button",
8880
+ className: "dock-sw" + (cfg.dingtalkEnabled ? " on" : ""),
8881
+ role: "switch",
8882
+ "aria-checked": cfg.dingtalkEnabled,
8883
+ "aria-label": "\u5F00\u5173\u9489\u9489\u63A8\u9001",
8884
+ disabled: source === "client",
8885
+ onClick: () => {
8886
+ if (source !== "client") patch({ dingtalkEnabled: !cfg.dingtalkEnabled });
8887
+ }
8888
+ }
8889
+ )
8890
+ ] })
8891
+ ] }),
8892
+ source === "client" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-channel-off", children: "\u672C\u673A\u914D\u7F6E\u6A21\u5F0F\u4E0D\u4FEE\u6539\u7FA4\u673A\u5668\u4EBA\uFF1B\u5207\u56DE\u670D\u52A1\u7AEF\u914D\u7F6E\u540E\u53EF\u7F16\u8F91 Webhook\u3002" }) : !cfg.dingtalkEnabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-channel-off", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u9489\u9489\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-body", children: [
8893
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8894
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u6D88\u606F\u53E3\u5F84" }),
8895
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModePicker, { value: cfg.pushMode || "detailed", title: "\u9489\u9489\u6D88\u606F", onChange: (v) => patch({ pushMode: v }) }),
8896
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7B80\u6D01\uFF1D\u4EFB\u52A1\u4E0E\u7ED3\u679C\uFF1B\u9002\u4E2D\uFF1D\u52A0\u6A21\u578B/\u8017\u65F6\uFF1B\u8BE6\u7EC6\uFF1D\u518D\u52A0\u56DE\u5408\u3001Token \u4E0E\u6458\u8981\u3002" })
8897
+ ] }),
8898
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row dknt-row-webhook", children: [
8899
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "Webhook" }),
8900
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8901
+ "input",
8902
+ {
8903
+ type: "text",
8904
+ className: "dknt-input",
8905
+ spellCheck: false,
8906
+ value: cfg.dingtalkWebhook || "",
8907
+ placeholder: "https://oapi.dingtalk.com/robot/send?access_token=\u2026",
8908
+ onChange: (e) => {
8909
+ editingWebhookRef.current = true;
8910
+ setServerDraft(Object.assign({}, cfg, { dingtalkWebhook: e.target.value }));
8911
+ }
8912
+ }
8913
+ ),
8914
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8915
+ "button",
8916
+ {
8917
+ type: "button",
8918
+ className: "dknt-btn",
8919
+ disabled: !editingWebhookRef.current,
8920
+ onClick: saveWebhook,
8921
+ children: editingWebhookRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
8922
+ }
8923
+ )
8924
+ ] }),
8925
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8926
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
8927
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dknt-btn", disabled: testing, onClick: runDingtalkTest, children: testing ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
8928
+ testState ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub" + (testState.ok ? " dknt-ok" : " dknt-err"), children: [
8929
+ testState.ok ? "\u2713 " : "\u2717 ",
8930
+ testState.msg
8931
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
8932
+ ] }),
8933
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u9489\u9489\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u667A\u80FD\u7FA4\u52A9\u624B \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\uFF08Webhook\uFF09\uFF0C\u5B89\u5168\u8BBE\u7F6E\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
8934
+ ] })
8701
8935
  ] }),
8702
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u98DE\u4E66\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u7FA4\u673A\u5668\u4EBA \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\u673A\u5668\u4EBA\uFF08\u83B7\u53D6 Webhook \u5730\u5740\uFF09\uFF1B \u5B89\u5168\u8BBE\u7F6E\u5982\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
8703
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u98DE\u4E66\u3002" })
8704
- ] }, "feishu")
8705
- );
8936
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel", children: [
8937
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-head", children: [
8938
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-title-wrap", children: [
8939
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-title", children: "\u98DE\u4E66\u63A8\u9001" }),
8940
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-channel-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u4EE5\u5361\u7247\u5F62\u5F0F\u63A8\u9001\u5230\u98DE\u4E66\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF09" })
8941
+ ] }),
8942
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-sec-sw", children: [
8943
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-sec-swlabel" + (cfg.feishuEnabled ? " on" : ""), children: cfg.feishuEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
8944
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8945
+ "button",
8946
+ {
8947
+ type: "button",
8948
+ className: "dock-sw" + (cfg.feishuEnabled ? " on" : ""),
8949
+ role: "switch",
8950
+ "aria-checked": cfg.feishuEnabled,
8951
+ "aria-label": "\u5F00\u5173\u98DE\u4E66\u63A8\u9001",
8952
+ disabled: source === "client",
8953
+ onClick: () => {
8954
+ if (source !== "client") patch({ feishuEnabled: !cfg.feishuEnabled });
8955
+ }
8956
+ }
8957
+ )
8958
+ ] })
8959
+ ] }),
8960
+ source === "client" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-channel-off", children: "\u672C\u673A\u914D\u7F6E\u6A21\u5F0F\u4E0D\u4FEE\u6539\u7FA4\u673A\u5668\u4EBA\uFF1B\u5207\u56DE\u670D\u52A1\u7AEF\u914D\u7F6E\u540E\u53EF\u7F16\u8F91 Webhook\u3002" }) : !cfg.feishuEnabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-channel-off", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u98DE\u4E66\u3002" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-channel-body", children: [
8961
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8962
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u6D88\u606F\u53E3\u5F84" }),
8963
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModePicker, { value: cfg.pushMode || "detailed", title: "\u98DE\u4E66\u6D88\u606F", onChange: (v) => patch({ pushMode: v }) }),
8964
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7B80\u6D01\uFF1D\u4EFB\u52A1\u4E0E\u7ED3\u679C\uFF1B\u9002\u4E2D\uFF1D\u52A0\u6A21\u578B/\u8017\u65F6\uFF1B\u8BE6\u7EC6\uFF1D\u518D\u52A0\u56DE\u5408\u3001Token \u4E0E\u6458\u8981\u3002" })
8965
+ ] }),
8966
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row dknt-row-webhook", children: [
8967
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "Webhook" }),
8968
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8969
+ "input",
8970
+ {
8971
+ type: "text",
8972
+ className: "dknt-input",
8973
+ spellCheck: false,
8974
+ value: cfg.feishuWebhook || "",
8975
+ placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026",
8976
+ onChange: (e) => {
8977
+ editingFeishuRef.current = true;
8978
+ setServerDraft(Object.assign({}, cfg, { feishuWebhook: e.target.value }));
8979
+ }
8980
+ }
8981
+ ),
8982
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
8983
+ "button",
8984
+ {
8985
+ type: "button",
8986
+ className: "dknt-btn",
8987
+ disabled: !editingFeishuRef.current,
8988
+ onClick: saveFeishuWebhook,
8989
+ children: editingFeishuRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
8990
+ }
8991
+ )
8992
+ ] }),
8993
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dknt-row", children: [
8994
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
8995
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dknt-btn", disabled: feishuTesting, onClick: runFeishuTest, children: feishuTesting ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
8996
+ feishuTestState ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dknt-row-sub" + (feishuTestState.ok ? " dknt-ok" : " dknt-err"), children: [
8997
+ feishuTestState.ok ? "\u2713 " : "\u2717 ",
8998
+ feishuTestState.msg
8999
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
9000
+ ] }),
9001
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u98DE\u4E66\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u7FA4\u673A\u5668\u4EBA \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\u673A\u5668\u4EBA\uFF08\u83B7\u53D6 Webhook \u5730\u5740\uFF09\uFF1B\u5B89\u5168\u8BBE\u7F6E\u5982\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
9002
+ ] })
9003
+ ] })
9004
+ ] }, "robots")
9005
+ );
9006
+ }
8706
9007
  }
8707
9008
  if (saveErr) rows.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dknt-note dknt-err", children: saveErr }, "err"));
8708
9009
  rows.push(
@@ -8712,10 +9013,16 @@ function NotifyView(props) {
8712
9013
  }
8713
9014
  function NotifyStat(props) {
8714
9015
  const snap = useNotify(props && props.ctx);
8715
- const cfg = snap.status && snap.status.config;
9016
+ const cfg = snap.status ? effectiveNotifyConfig(snap.status.config) : null;
8716
9017
  if (snap.error) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dknt-err", children: "\u901A\u77E5\u72B6\u6001\u4E0D\u53EF\u7528\uFF08\u5BBF\u4E3B\u9700\u91CD\u542F\u52A0\u8F7D\u901A\u77E5\u8DEF\u7531\uFF09" });
8717
9018
  if (!cfg) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u7B49\u5F85\u901A\u77E5\u914D\u7F6E\u2026" });
8718
- const events = [cfg.notifyOnComplete ? "\u5B8C\u6210" : "", cfg.notifyOnError ? "\u5F02\u5E38" : "", cfg.notifyOnConfirm !== false ? "\u9700\u786E\u8BA4/\u9700\u56DE\u7B54" : ""].filter(Boolean);
9019
+ const anyChannel = (event) => MATRIX_COLUMNS.some((column) => eventEnabled(cfg, column.id, event));
9020
+ const events = [
9021
+ anyChannel("complete") ? "\u5B8C\u6210" : "",
9022
+ anyChannel("error") ? "\u5F02\u5E38" : "",
9023
+ anyChannel("confirm") ? "\u9700\u786E\u8BA4/\u9700\u56DE\u7B54" : "",
9024
+ anyChannel("stuck") ? "\u5361\u4F4F" : ""
9025
+ ].filter(Boolean);
8719
9026
  const voiceMode = cfg.voiceMode === "detailed" ? "\xB7\u8BE6" : cfg.voiceMode === "medium" ? "\xB7\u9002" : "\xB7\u7B80";
8720
9027
  const voice = !cfg.voiceNotify ? "" : voiceClientEnabled() ? "\u8BED\u97F3\u64AD\u62A5" + voiceMode : "\u8BED\u97F3\u64AD\u62A5\xB7\u672C\u673A\u5DF2\u5173";
8721
9028
  const extras = [cfg.soundNotify !== false ? "\u63D0\u793A\u97F3" : "", cfg.systemNotify ? "\u7CFB\u7EDF\u901A\u77E5" : "", voice].filter(Boolean);
@@ -8765,6 +9072,48 @@ var css3 = [
8765
9072
  ".dknt-row-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
8766
9073
  ".dknt-miniswitch{cursor:pointer;flex:none;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 12px;font-family:inherit;font-size:11px;line-height:18px;}",
8767
9074
  ".dknt-miniswitch.on{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
9075
+ // 配置来源与页签
9076
+ ".dknt-source{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;padding:10px 12px;}",
9077
+ ".dknt-source-info{display:flex;flex-direction:column;gap:2px;flex:1;min-width:180px;}",
9078
+ ".dknt-source-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);}",
9079
+ ".dknt-source-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
9080
+ ".dknt-seg{display:inline-flex;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;overflow:hidden;flex:none;}",
9081
+ ".dknt-seg-btn{cursor:pointer;border:0;background:transparent;color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;padding:5px 12px;}",
9082
+ ".dknt-seg-btn + .dknt-seg-btn{border-left:1px solid var(--dsw-alias-border-l2);}",
9083
+ ".dknt-seg-btn.on{background:var(--dk-accent-soft);color:var(--dk-accent);font-weight:600;}",
9084
+ ".dknt-tabs{display:flex;gap:4px;border-bottom:1px solid var(--dsw-alias-border-l1);padding:0 2px;}",
9085
+ ".dknt-tab{cursor:pointer;border:0;background:transparent;color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:13px;padding:7px 12px;border-bottom:2px solid transparent;margin-bottom:-1px;}",
9086
+ ".dknt-tab.on{color:var(--dk-accent);border-bottom-color:var(--dk-accent);font-weight:600;}",
9087
+ // 事件 × 渠道矩阵
9088
+ ".dknt-matrix-wrap{overflow-x:auto;}",
9089
+ ".dknt-matrix{display:flex;flex-direction:column;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;overflow:hidden;min-width:620px;}",
9090
+ ".dknt-matrix-row{display:grid;grid-template-columns:minmax(150px,1.4fr) repeat(6,minmax(56px,1fr));align-items:center;}",
9091
+ ".dknt-matrix-row:nth-child(even){background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 55%,transparent);}",
9092
+ ".dknt-matrix-head{background:var(--dsw-alias-bg-layer-2);border-bottom:1px solid var(--dsw-alias-border-l1);}",
9093
+ ".dknt-matrix-col{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);text-align:center;padding:7px 4px;display:flex;flex-direction:column;align-items:center;gap:1px;}",
9094
+ ".dknt-matrix-col em{font-style:normal;font-size:10px;font-weight:400;color:var(--dsw-alias-label-tertiary);}",
9095
+ ".dknt-matrix-col.on em{color:var(--dsw-alias-state-success-primary);}",
9096
+ ".dknt-matrix-event{display:flex;flex-direction:column;gap:1px;padding:8px 10px;font-size:12px;color:var(--dsw-alias-label-primary);}",
9097
+ ".dknt-matrix-event small{font-size:10px;color:var(--dsw-alias-label-tertiary);}",
9098
+ ".dknt-cell{justify-self:center;cursor:pointer;width:24px;height:24px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:transparent;font-family:inherit;font-size:12px;line-height:1;display:inline-flex;align-items:center;justify-content:center;margin:5px 0;}",
9099
+ ".dknt-cell.on{border-color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 14%,transparent);color:var(--dsw-alias-state-success-primary);}",
9100
+ ".dknt-cell-na{cursor:default;border-style:dashed;color:var(--dsw-alias-label-tertiary);}",
9101
+ ".dknt-cell.disabled{opacity:.4;cursor:not-allowed;}",
9102
+ ".dknt-matrix-legend{display:flex;gap:12px;flex-wrap:wrap;padding-top:6px;font-size:10px;color:var(--dsw-alias-label-tertiary);}",
9103
+ ".dknt-matrix-legend span{display:inline-flex;align-items:center;gap:4px;}",
9104
+ ".dknt-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-label-tertiary);display:inline-block;}",
9105
+ ".dknt-dot.on{background:var(--dsw-alias-state-success-primary);}",
9106
+ // 渠道卡片
9107
+ ".dknt-channels{display:flex;flex-direction:column;gap:10px;}",
9108
+ ".dknt-channel{border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1);overflow:hidden;}",
9109
+ ".dknt-channel-head{display:flex;align-items:center;gap:10px;padding:10px 12px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 45%,transparent);border-bottom:1px solid var(--dsw-alias-border-l1);}",
9110
+ ".dknt-channel-title-wrap{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0;}",
9111
+ ".dknt-channel-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);}",
9112
+ ".dknt-channel-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
9113
+ ".dknt-channel-body{display:flex;flex-direction:column;gap:8px;padding:10px 12px;}",
9114
+ ".dknt-channel-off{padding:10px 12px;font-size:12px;color:var(--dsw-alias-label-tertiary);}",
9115
+ ".dknt-modes{display:inline-flex;gap:4px;flex:none;}",
9116
+ ".dknt-note-box{border:1px solid var(--dsw-alias-border-l1);border-radius:8px;padding:8px 10px;background:var(--dsw-alias-bg-layer-1);}",
8768
9117
  // 音效选择卡(名称 + 播放键;选中态描边)
8769
9118
  ".dknt-sounds{display:flex;gap:6px;flex-wrap:wrap;}",
8770
9119
  ".dknt-sound{flex:1;min-width:104px;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:6px 10px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2);cursor:pointer;font-family:inherit;transition:border-color .15s var(--ds-ease-in-out);}",
@@ -8787,7 +9136,7 @@ var feature8 = {
8787
9136
  name: "\u4EFB\u52A1\u901A\u77E5",
8788
9137
  order: 140,
8789
9138
  accent: "#f59e0b",
8790
- description: "\u4EFB\u52A1\u5B8C\u6210/\u5F02\u5E38/\u9700\u786E\u8BA4\u901A\u77E5\uFF1A\u9875\u5185\u5361\u7247\u3001\u63D0\u793A\u97F3\u3001\u7CFB\u7EDF\u901A\u77E5\u3001\u9489\u9489/\u98DE\u4E66\u7FA4\u673A\u5668\u4EBA\u63A8\u9001\uFF08\u72EC\u7ACB\u5F00\u5173\uFF09",
9139
+ description: "\u4EFB\u52A1\u5B8C\u6210/\u5F02\u5E38/\u9700\u786E\u8BA4/\u9700\u56DE\u7B54/\u5361\u4F4F\u901A\u77E5\uFF1A\u670D\u52A1\u7AEF\u6216\u672C\u673A\u914D\u7F6E\u3001\u4E8B\u4EF6\xD7\u6E20\u9053\u52FE\u9009\u3001\u9875\u5185\u5361\u7247/\u63D0\u793A\u97F3/\u7CFB\u7EDF\u901A\u77E5/\u8BED\u97F3\u64AD\u62A5/\u9489\u9489\u98DE\u4E66\u63A8\u9001\uFF08\u5404\u81EA\u72EC\u7ACB\u5F00\u5173\uFF09",
8791
9140
  css: css3,
8792
9141
  View: NotifyView,
8793
9142
  HomeStat: NotifyStat,
@@ -14202,9 +14551,388 @@ var feature12 = {
14202
14551
  HomeStat: MobileRelayHomeStat
14203
14552
  };
14204
14553
 
14554
+ // features/mobile/view.js
14555
+ var import_react24 = __toESM(require("react"), 1);
14556
+ var import_react25 = require("react");
14557
+ var MOBILE_QUERY = "(max-width: 767px)";
14558
+ var COARSE_QUERY = "(pointer: coarse) and (hover: none)";
14559
+ function mobileActive() {
14560
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
14561
+ try {
14562
+ return window.matchMedia(MOBILE_QUERY).matches || window.matchMedia(COARSE_QUERY).matches;
14563
+ } catch {
14564
+ return false;
14565
+ }
14566
+ }
14567
+ var MOBILE_CSS = [
14568
+ "/* \u89E6\u63A7\u4E0E\u8F93\u5165\uFF1A\u7C97\u6307\u9488\u771F\u673A\uFF08\u4E0D\u5206\u5BBD\u5EA6\uFF09 */",
14569
+ "@media (pointer: coarse) and (hover: none){",
14570
+ ' body[data-dk-mobile="1"] :is(textarea,input:not([type]),input[type="text"],input[type="search"],input[type="url"],input[type="password"],input[type="number"],input[type="email"],[contenteditable="true"]){font-size:16px !important;}',
14571
+ ' body[data-dk-mobile="1"] :is(button,[role="button"]){-webkit-tap-highlight-color:transparent;touch-action:manipulation;}',
14572
+ "}",
14573
+ "@media (max-width:767px){",
14574
+ ' body[data-dk-mobile="1"] :is(textarea,input:not([type]),input[type="text"],input[type="search"],input[type="url"],input[type="password"],input[type="number"],input[type="email"],[contenteditable="true"]){font-size:16px !important;}',
14575
+ ' body[data-dk-mobile="1"] :is(button,[role="button"]){-webkit-tap-highlight-color:transparent;touch-action:manipulation;}',
14576
+ ' body[data-dk-mobile="1"] pre{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;}',
14577
+ ' body[data-dk-mobile="1"] code{overflow-wrap:anywhere;}',
14578
+ ' body[data-dk-mobile="1"] pre code{overflow-wrap:normal;}',
14579
+ ' body[data-dk-mobile="1"] .dockchip-row{display:none;}',
14580
+ ' body[data-dk-mobile="1"] [data-sidebar-opener]{position:relative;}',
14581
+ ' body[data-dk-mobile="1"] [data-sidebar-opener]::after{content:"";position:absolute;left:50%;top:50%;width:44px;height:44px;transform:translate(-50%,-50%);}',
14582
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"] [class*="options"]{padding-left:max(16px,env(safe-area-inset-left,0px));padding-right:max(16px,env(safe-area-inset-right,0px));}',
14583
+ ' body[data-dk-mobile="1"] [class*="scrollBody"]{padding-bottom:env(safe-area-inset-bottom,0px) !important;}',
14584
+ " /* \u529F\u80FD\u575E\u9762\u677F\uFF08.dockm-*\uFF09\u6302\u5728 .overlayLayer(z20) \u5185\uFF0C\u800C\u624B\u673A\u62BD\u5C49 .sidebarCol \u662F z71\u2014\u2014\u9762\u677F\u867D\u662F\u5168\u5C4F\u5374\u88AB\u62BD\u5C49\u76D6\u4F4F\u3002\u628A overlayLayer \u62AC\u5230\u62BD\u5C49\u4E4B\u4E0A\uFF0C\u529F\u80FD\u575E/\u5168\u5C40\u6D6E\u5C42\u624D\u80FD\u5168\u5C4F\u76D6\u4F4F\u62BD\u5C49\u3002 */",
14585
+ ' body[data-dk-mobile="1"] [class*="overlayLayer"]{z-index:100 !important;}',
14586
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"][data-dsh-mobile-stack]{display:flex !important;flex-direction:column !important;width:100vw !important;max-width:100vw !important;height:100dvh !important;max-height:none !important;border-radius:0 !important;overflow:hidden !important;}',
14587
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"][data-dsh-mobile-stack] > [class*="header"]{order:0;flex:none;width:auto !important;height:auto !important;padding:8px 12px !important;justify-content:flex-end !important;}',
14588
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"][data-dsh-mobile-stack] > [class*="navTitle"]{order:1;flex:none;width:auto !important;padding:2px 16px 8px !important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}',
14589
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"][data-dsh-mobile-stack] > nav{order:2;flex:none;width:auto !important;height:auto !important;padding:0 8px 8px !important;overflow-x:auto;overflow-y:hidden;}',
14590
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"][data-dsh-mobile-stack] > nav [class*="navList"]{flex-direction:row !important;}',
14591
+ ' body[data-dk-mobile="1"] [role="dialog"][class*="panel"][data-dsh-mobile-stack] > [class*="options"]{order:3;flex:1 1 auto !important;min-height:0 !important;width:auto !important;overflow-y:auto !important;padding-bottom:max(16px,env(safe-area-inset-bottom,0px)) !important;}',
14592
+ ' body[data-dk-mobile="1"][data-dsh-mobile-legacy] [class$="frame"]{grid-template-columns:0px minmax(0,1fr) 0px !important;}',
14593
+ ' body[data-dk-mobile="1"][data-dsh-mobile-legacy] [class$="frame"] [class*="sidebarCol"]{position:fixed !important;top:0 !important;bottom:0 !important;left:0 !important;width:min(86vw,300px) !important;z-index:80 !important;box-shadow:0 12px 48px rgba(0,0,0,.45);transform:none !important;visibility:visible !important;transition:transform .22s ease !important;}',
14594
+ ' body[data-dk-mobile="1"][data-dsh-mobile-legacy] [class$="frame"][data-sidebar-collapsed] [class*="sidebarCol"]{transform:translateX(-105%) !important;visibility:hidden !important;transition:transform .22s ease, visibility 0s linear .22s !important;}',
14595
+ ' body[data-dk-mobile="1"] .dsh-mobile-scrim{position:fixed;inset:0;z-index:75;background:rgba(8,10,14,.45);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);touch-action:none;}',
14596
+ ' body[data-dk-mobile="1"] .dsh-mobile-burger{position:fixed;left:calc(4px + env(safe-area-inset-left,0px));top:calc(4px + env(safe-area-inset-top,0px));z-index:66;box-sizing:border-box;width:44px;height:44px;display:flex;align-items:center;justify-content:center;padding:0;border:0;background:transparent;color:var(--dsw-alias-label-primary,#e6eaf2);-webkit-tap-highlight-color:transparent;touch-action:manipulation;}',
14597
+ ' body[data-dk-mobile="1"] .dsh-mobile-burger svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;}',
14598
+ ' body[data-dk-mobile="1"] .dsh-mobile-burger:active{background:color-mix(in srgb,currentColor 12%,transparent);}',
14599
+ ' body[data-dk-mobile="1"][data-dsh-mobile-legacy] [class$="frame"] header:has([class*="titleRow"]){padding-left:calc(48px + env(safe-area-inset-left,0px));}',
14600
+ ' html.dsh-dock-kbd body[data-dk-mobile="1"] .dsh-mobile-burger{display:none !important;}',
14601
+ "}"
14602
+ ].join("\n");
14603
+ var STYLE_ATTR = "data-dsh-mobile-runtime";
14604
+ var BODY_ATTR = "data-dk-mobile";
14605
+ var LEGACY_ATTR = "data-dsh-mobile-legacy";
14606
+ var currentDispose = null;
14607
+ function applyRuntime() {
14608
+ if (typeof window === "undefined" || typeof document === "undefined") return function() {
14609
+ };
14610
+ const doc = document;
14611
+ const body = doc.body;
14612
+ if (!body) return function() {
14613
+ };
14614
+ if (currentDispose) {
14615
+ try {
14616
+ currentDispose();
14617
+ } catch (e) {
14618
+ }
14619
+ currentDispose = null;
14620
+ }
14621
+ body.setAttribute(BODY_ATTR, "1");
14622
+ let styleEl = doc.querySelector("style[" + STYLE_ATTR + "]");
14623
+ if (!styleEl) {
14624
+ styleEl = doc.createElement("style");
14625
+ styleEl.setAttribute(STYLE_ATTR, "");
14626
+ styleEl.textContent = MOBILE_CSS;
14627
+ doc.head.appendChild(styleEl);
14628
+ }
14629
+ const mql = window.matchMedia ? window.matchMedia(MOBILE_QUERY) : null;
14630
+ const vv = window.visualViewport || null;
14631
+ const phone = function() {
14632
+ return !!(mql && mql.matches);
14633
+ };
14634
+ const frame = function() {
14635
+ return doc.querySelector('[class$="frame"]');
14636
+ };
14637
+ const isCollapsed = function() {
14638
+ const f = frame();
14639
+ return !!(f && f.hasAttribute("data-sidebar-collapsed"));
14640
+ };
14641
+ let scrim = null;
14642
+ let burger = null;
14643
+ let observer = null;
14644
+ let timer = 0;
14645
+ function sidebarOpenToggle() {
14646
+ const b = doc.querySelector("[data-sidebar-opener]") || doc.querySelector("[data-sidebar-toggle]");
14647
+ if (b && typeof b.click === "function") b.click();
14648
+ }
14649
+ function clearStack() {
14650
+ const panels = doc.querySelectorAll('[role="dialog"][class*="panel"][data-dsh-mobile-stack]');
14651
+ for (let i = 0; i < panels.length; i++) panels[i].removeAttribute("data-dsh-mobile-stack");
14652
+ }
14653
+ function dialogStackSync() {
14654
+ const panel = doc.querySelector('[role="dialog"][class*="panel"]');
14655
+ if (!panel) return;
14656
+ let nav = null;
14657
+ let opt = null;
14658
+ const kids = panel.children;
14659
+ for (let i = 0; i < kids.length; i++) {
14660
+ const k = kids[i];
14661
+ if (!nav && k.tagName === "NAV") nav = k;
14662
+ if (!opt && k.className && String(k.className).indexOf("options") >= 0) opt = k;
14663
+ }
14664
+ if (!nav || !opt) {
14665
+ panel.removeAttribute("data-dsh-mobile-stack");
14666
+ return;
14667
+ }
14668
+ const a = nav.getBoundingClientRect();
14669
+ const b = opt.getBoundingClientRect();
14670
+ if (!a.width || !b.width) return;
14671
+ const sideBySide = b.left >= a.right - 8 && b.top < a.bottom - 4 && b.bottom > a.top + 4;
14672
+ if (sideBySide) panel.setAttribute("data-dsh-mobile-stack", "1");
14673
+ else panel.removeAttribute("data-dsh-mobile-stack");
14674
+ }
14675
+ function removeChrome() {
14676
+ if (scrim) {
14677
+ scrim.remove();
14678
+ scrim = null;
14679
+ }
14680
+ if (burger) {
14681
+ burger.remove();
14682
+ burger = null;
14683
+ }
14684
+ body.removeAttribute(LEGACY_ATTR);
14685
+ }
14686
+ function ensureChrome() {
14687
+ if (!scrim) {
14688
+ scrim = doc.createElement("div");
14689
+ scrim.className = "dsh-mobile-scrim";
14690
+ scrim.style.display = "none";
14691
+ scrim.addEventListener("click", function() {
14692
+ if (!isCollapsed()) sidebarOpenToggle();
14693
+ });
14694
+ body.appendChild(scrim);
14695
+ }
14696
+ if (!burger) {
14697
+ burger = doc.createElement("button");
14698
+ burger.type = "button";
14699
+ burger.className = "dsh-mobile-burger";
14700
+ burger.setAttribute("aria-label", "\u6253\u5F00\u4F1A\u8BDD\u5217\u8868");
14701
+ burger.setAttribute("aria-expanded", "false");
14702
+ burger.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 7h16"/><path d="M4 12h16"/><path d="M4 17h16"/></svg>';
14703
+ burger.addEventListener("click", function() {
14704
+ sidebarOpenToggle();
14705
+ });
14706
+ body.appendChild(burger);
14707
+ }
14708
+ }
14709
+ function legacySync() {
14710
+ const f = frame();
14711
+ const legacy = !!f && phone() && !f.hasAttribute("data-sidebar-drawer");
14712
+ if (!legacy) {
14713
+ removeChrome();
14714
+ return;
14715
+ }
14716
+ body.setAttribute(LEGACY_ATTR, "1");
14717
+ ensureChrome();
14718
+ const collapsed = isCollapsed();
14719
+ if (scrim) scrim.style.display = collapsed ? "none" : "";
14720
+ if (burger) {
14721
+ burger.style.display = "";
14722
+ burger.setAttribute("aria-expanded", collapsed ? "false" : "true");
14723
+ }
14724
+ }
14725
+ function kbdSync() {
14726
+ if (!vv) return;
14727
+ const kbd = vv.height > 0 && window.innerHeight - vv.height > 120;
14728
+ const de = doc.documentElement;
14729
+ if (kbd) de.classList.add("dsh-dock-kbd");
14730
+ else de.classList.remove("dsh-dock-kbd");
14731
+ }
14732
+ let dockAutoClosed = false;
14733
+ function dockOpen() {
14734
+ return !!doc.querySelector(".dockm-dialog");
14735
+ }
14736
+ function tick() {
14737
+ try {
14738
+ kbdSync();
14739
+ if (phone()) {
14740
+ const dopen = dockOpen();
14741
+ if (dopen && !isCollapsed() && !dockAutoClosed) {
14742
+ dockAutoClosed = true;
14743
+ sidebarOpenToggle();
14744
+ }
14745
+ if (!dopen) dockAutoClosed = false;
14746
+ dialogStackSync();
14747
+ legacySync();
14748
+ } else {
14749
+ clearStack();
14750
+ removeChrome();
14751
+ dockAutoClosed = false;
14752
+ }
14753
+ } catch (e) {
14754
+ }
14755
+ }
14756
+ tick();
14757
+ if (typeof MutationObserver !== "undefined") {
14758
+ observer = new MutationObserver(function() {
14759
+ tick();
14760
+ });
14761
+ try {
14762
+ observer.observe(doc.documentElement, { attributes: true, attributeFilter: ["data-sidebar-collapsed", "data-sidebar-drawer"], subtree: true });
14763
+ observer.observe(body, { childList: true, subtree: true });
14764
+ } catch (e) {
14765
+ }
14766
+ }
14767
+ timer = window.setInterval(tick, 1200);
14768
+ const onResize = function() {
14769
+ tick();
14770
+ };
14771
+ window.addEventListener("resize", onResize);
14772
+ if (vv && vv.addEventListener) vv.addEventListener("resize", kbdSync);
14773
+ if (mql && mql.addEventListener) mql.addEventListener("change", tick);
14774
+ else if (mql && mql.addListener) mql.addListener(tick);
14775
+ const dispose = function() {
14776
+ if (currentDispose === dispose) currentDispose = null;
14777
+ try {
14778
+ if (observer) observer.disconnect();
14779
+ } catch (e) {
14780
+ }
14781
+ if (timer) window.clearInterval(timer);
14782
+ window.removeEventListener("resize", onResize);
14783
+ if (vv && vv.removeEventListener) vv.removeEventListener("resize", kbdSync);
14784
+ if (mql && mql.removeEventListener) mql.removeEventListener("change", tick);
14785
+ else if (mql && mql.removeListener) mql.removeListener(tick);
14786
+ try {
14787
+ doc.documentElement.classList.remove("dsh-dock-kbd");
14788
+ } catch (e) {
14789
+ }
14790
+ try {
14791
+ clearStack();
14792
+ } catch (e) {
14793
+ }
14794
+ removeChrome();
14795
+ try {
14796
+ body.removeAttribute(BODY_ATTR);
14797
+ } catch (e) {
14798
+ }
14799
+ try {
14800
+ if (styleEl && styleEl.parentNode) styleEl.parentNode.removeChild(styleEl);
14801
+ } catch (e) {
14802
+ }
14803
+ };
14804
+ currentDispose = dispose;
14805
+ return dispose;
14806
+ }
14807
+ function MobileOverlay() {
14808
+ const [active, setActive] = (0, import_react25.useState)(function() {
14809
+ return mobileActive();
14810
+ });
14811
+ (0, import_react25.useEffect)(function() {
14812
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
14813
+ let mqs = [];
14814
+ try {
14815
+ mqs = [window.matchMedia(MOBILE_QUERY), window.matchMedia(COARSE_QUERY)];
14816
+ } catch (e) {
14817
+ return void 0;
14818
+ }
14819
+ const update = function() {
14820
+ setActive(mqs.some(function(m) {
14821
+ return m.matches;
14822
+ }));
14823
+ };
14824
+ update();
14825
+ for (let i = 0; i < mqs.length; i++) {
14826
+ const m = mqs[i];
14827
+ if (m.addEventListener) m.addEventListener("change", update);
14828
+ else if (m.addListener) m.addListener(update);
14829
+ }
14830
+ return function() {
14831
+ for (let i = 0; i < mqs.length; i++) {
14832
+ const m = mqs[i];
14833
+ if (m.removeEventListener) m.removeEventListener("change", update);
14834
+ else if (m.removeListener) m.removeListener(update);
14835
+ }
14836
+ };
14837
+ }, []);
14838
+ (0, import_react25.useEffect)(function() {
14839
+ if (!active) return void 0;
14840
+ return applyRuntime();
14841
+ }, [active]);
14842
+ return null;
14843
+ }
14844
+ function useViewport() {
14845
+ const [size, setSize] = (0, import_react25.useState)(function() {
14846
+ return typeof window === "undefined" ? null : { w: window.innerWidth, h: window.innerHeight };
14847
+ });
14848
+ (0, import_react25.useEffect)(function() {
14849
+ if (typeof window === "undefined") return void 0;
14850
+ const update = function() {
14851
+ setSize({ w: window.innerWidth, h: window.innerHeight });
14852
+ };
14853
+ window.addEventListener("resize", update);
14854
+ return function() {
14855
+ window.removeEventListener("resize", update);
14856
+ };
14857
+ }, []);
14858
+ return size;
14859
+ }
14860
+ function MobileView() {
14861
+ const size = useViewport();
14862
+ const [active, setActive] = (0, import_react25.useState)(function() {
14863
+ return mobileActive();
14864
+ });
14865
+ const [drawer, setDrawer] = (0, import_react25.useState)(false);
14866
+ (0, import_react25.useEffect)(function() {
14867
+ if (typeof window === "undefined") return void 0;
14868
+ const tick = function() {
14869
+ setActive(mobileActive());
14870
+ const f = document.querySelector('[class$="frame"]');
14871
+ setDrawer(!!(f && f.hasAttribute("data-sidebar-drawer")));
14872
+ };
14873
+ tick();
14874
+ const t = setInterval(tick, 1e3);
14875
+ return function() {
14876
+ clearInterval(t);
14877
+ };
14878
+ }, []);
14879
+ const mode = !active ? "\u672A\u547D\u4E2D" : window.matchMedia && window.matchMedia(MOBILE_QUERY).matches ? drawer ? "\u62BD\u5C49\u6A21\u5F0F\uFF08\u539F\u751F\uFF09" : "\u65E7\u7248\u515C\u5E95\uFF08\u6D6E\u5C42\u62BD\u5C49\uFF09" : "\u4EC5\u89E6\u63A7\u4F18\u5316";
14880
+ return import_react24.default.createElement(
14881
+ "div",
14882
+ { className: "dkmob-root" },
14883
+ import_react24.default.createElement(
14884
+ "div",
14885
+ { className: "dkmob-row" },
14886
+ import_react24.default.createElement("span", { className: "dkmob-label" }, "\u624B\u673A\u6A21\u5F0F"),
14887
+ import_react24.default.createElement("span", { className: "dkmob-state" + (active ? " on" : "") }, active ? "\u5DF2\u547D\u4E2D" : "\u672A\u547D\u4E2D"),
14888
+ import_react24.default.createElement("span", { className: "dkmob-dim" }, size ? size.w + "\xD7" + size.h + "px" : "")
14889
+ ),
14890
+ import_react24.default.createElement(
14891
+ "div",
14892
+ { className: "dkmob-row" },
14893
+ import_react24.default.createElement("span", { className: "dkmob-label" }, "\u5F53\u524D\u5F62\u6001"),
14894
+ import_react24.default.createElement("span", { className: "dkmob-state" + (active ? " on" : "") }, mode)
14895
+ ),
14896
+ import_react24.default.createElement(
14897
+ "div",
14898
+ { className: "dkmob-note" },
14899
+ "\u751F\u6548\u4E2D\u7684\u4F18\u5316\uFF1A\u8F93\u5165\u7C7B\u63A7\u4EF6\u5B57\u53F7 16px\uFF08\u9632 iOS \u805A\u7126\u6574\u9875\u7F29\u653E\uFF09\xB7 \u539F\u751F\u4FA7\u680F\u5F00\u5173\u70ED\u533A\u6269\u5230 44\xD744 \xB7 ",
14900
+ "\u53BB\u70B9\u6309\u9AD8\u4EAE\u4E0E\u53CC\u51FB\u7F29\u653E\u5224\u5B9A \xB7 \u4EE3\u7801\u5757\u6A2A\u5411\u6EDA\u52A8 / \u884C\u5185\u4EE3\u7801\u6362\u884C \xB7 \u4F1A\u8BDD\u8F93\u5165\u884C\u7684\u4F59\u989D/\u7528\u91CF chip \u6536\u8D77 \xB7 ",
14901
+ "\u8BBE\u7F6E\u5F39\u5C42\u5185\u5BB9\u5B89\u5168\u533A\u5185\u8FB9\u8DDD\u3002\u65E7\u7248 dsh\uFF08<768 \u4ECD\u662F\u4E24\u680F\u5F39\u5C42\u6216\u9759\u6001\u56FE\u6807\u8F68\u9053\uFF09\u4F1A\u81EA\u52A8\u515C\u5E95\u4E3A\u5355\u5217 / \u6D6E\u5C42\u62BD\u5C49\u3002",
14902
+ "\u5173\u95ED\u672C\u529F\u80FD\u5373\u5168\u90E8\u8FD8\u539F\u2014\u2014\u8FD0\u884C\u65F6\u6837\u5F0F\u3001body \u5C5E\u6027\u3001\u906E\u7F69/\u6309\u94AE\u4E0E\u6240\u6709\u76D1\u542C\u5668\u4E00\u5E76\u79FB\u9664\uFF0C\u9875\u9762\u4E0D\u6B8B\u7559\u4EFB\u4F55\u6CE8\u5165\u3002"
14903
+ )
14904
+ );
14905
+ }
14906
+ function MobileStat() {
14907
+ const active = mobileActive();
14908
+ if (!active) return import_react24.default.createElement("span", null, "\u5F53\u524D\u89C6\u53E3\u672A\u547D\u4E2D\u624B\u673A\u5F62\u6001\uFF0C\u672A\u542F\u7528\u4EFB\u4F55\u4F18\u5316");
14909
+ return import_react24.default.createElement("span", null, "\u624B\u673A\u6A21\u5F0F\u751F\u6548\u4E2D\uFF0816px \u8F93\u5165 / \u89E6\u63A7\u70ED\u533A / \u4EE3\u7801\u6EDA\u52A8 / \u5F39\u5C42\u515C\u5E95\uFF09");
14910
+ }
14911
+ var css6 = [
14912
+ ".dkmob-root{display:flex;flex-direction:column;gap:10px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.6;}",
14913
+ ".dkmob-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}",
14914
+ ".dkmob-label{font-weight:600;flex:none;}",
14915
+ ".dkmob-state{flex:none;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 10px;font-size:11px;}",
14916
+ ".dkmob-state.on{color:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary);}",
14917
+ ".dkmob-dim{color:var(--dsw-alias-label-secondary);font-size:12px;}",
14918
+ ".dkmob-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.7;border-top:1px solid var(--dsw-alias-border-l1);padding-top:10px;}"
14919
+ ].join("\n");
14920
+ var feature13 = {
14921
+ id: "mobile",
14922
+ name: "\u624B\u673A\u9002\u914D",
14923
+ order: 170,
14924
+ accent: "#34d399",
14925
+ description: "\u624B\u673A/\u7A84\u5C4F\u4F53\u9A8C\u4F18\u5316\uFF1A16px \u8F93\u5165\u9632\u7F29\u653E\u3001\u89E6\u63A7\u70ED\u533A\u3001\u4EE3\u7801\u5757\u6EDA\u52A8\u3001\u4F1A\u8BDD chip \u6536\u8D77\u3001\u8BBE\u7F6E\u5F39\u5C42\u5355\u5217\u4E0E\u65E7\u7248\u62BD\u5C49\u515C\u5E95\uFF1B\u5173\u95ED\u540E\u96F6\u6B8B\u7559",
14926
+ defaultEnabled: false,
14927
+ css: css6,
14928
+ Overlay: MobileOverlay,
14929
+ View: MobileView,
14930
+ HomeStat: MobileStat
14931
+ };
14932
+
14205
14933
  // src/client.jsx
14206
- var DOCK_VERSION = "0.20.0";
14207
- var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9, feature10, feature11, feature12];
14934
+ var DOCK_VERSION = "0.21.0";
14935
+ var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7, feature8, feature9, feature10, feature11, feature12, feature13];
14208
14936
  var PLANNED_FEATURES = [];
14209
14937
  var PLANNED_NOTES = {};
14210
14938
  var externalDefs = [];
@@ -14318,6 +15046,12 @@ var SHELL_CSS = [
14318
15046
  ".dockm-name{display:flex;align-items:center;gap:8px;font-weight:600;font-size:15px;}",
14319
15047
  ".dockm-desc{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;}",
14320
15048
  ".dockm-view{display:flex;flex-direction:column;gap:8px;border-top:1px solid var(--dsw-alias-border-l1);padding-top:10px;}",
15049
+ ".dockm-page{box-sizing:border-box;height:100%;overflow:auto;padding:20px 24px 32px;}",
15050
+ ".dockm-page-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:16px;}",
15051
+ ".dockm-page-icon{flex:none;display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);}",
15052
+ ".dockm-page-titles{min-width:0;}",
15053
+ ".dockm-page-title{font-size:17px;font-weight:600;color:var(--dsw-alias-label-primary);line-height:1.3;}",
15054
+ ".dockm-page-sub{font-size:12px;color:var(--dsw-alias-label-tertiary);margin-top:2px;}",
14321
15055
  ".dockm-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;border-top:1px solid var(--dsw-alias-border-l1);padding-top:10px;}",
14322
15056
  ".dockm-err{color:var(--dsw-alias-state-error-primary);}",
14323
15057
  ".dockm-foot{margin-top:auto;display:flex;align-items:center;gap:8px;color:var(--dsw-alias-label-tertiary);font-size:11px;border-top:1px solid var(--dsw-alias-border-l1);padding-top:10px;flex-wrap:wrap;}",
@@ -14349,7 +15083,11 @@ var SHELL_CSS = [
14349
15083
  ".dockm-foot-swlabel.on{color:var(--dsw-alias-state-success-primary);}",
14350
15084
  // 窄屏:功能坞是一级工作台而不是被压扁的桌面弹窗。全屏承接安全区,导航改横向,
14351
15085
  // 禁用桌面拖拽/缩放,所有导航和关闭动作保持至少 44px 的可点击面积。
14352
- "@media (max-width:680px){.dockm-backdrop{align-items:stretch;justify-content:stretch;background:var(--dsw-alias-bg-layer-2);backdrop-filter:none}.dockm-dialog,.dockm-dialog.dockm-max{position:fixed!important;left:0!important;top:0!important;right:auto!important;bottom:auto!important;width:100dvw!important;height:100dvh!important;min-height:100dvh;border:0;border-radius:0;box-shadow:none}.dockm-dialog.dockm-min .dockm-body{display:flex}.dockm-head{min-height:60px;box-sizing:border-box;padding:calc(env(safe-area-inset-top) + 8px) 12px 8px;cursor:default;touch-action:manipulation}.dockm-sub,.dockm-win,.dockm-resize{display:none}.dockm-title{font-size:16px}.dockm-close{width:44px;height:44px;font-size:17px}.dockm-body{flex-direction:column;min-height:0}.dockm-nav{box-sizing:border-box;width:auto;max-width:100%;min-height:56px;flex-direction:row;gap:6px;padding:6px 10px;overflow-x:auto;overflow-y:hidden;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l1);scrollbar-width:none;overscroll-behavior-x:contain}.dockm-nav::-webkit-scrollbar{display:none}.dockm-nav-item{flex:none;min-height:44px;padding:0 12px;font-size:13px;touch-action:manipulation}.dockm-nav-item .dockm-badge{display:none}.dockm-content{padding:16px max(16px,env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left));gap:14px;overscroll-behavior:contain}.dockm-content-head{gap:5px}.dockm-name{font-size:16px}.dockm-desc{font-size:13px;line-height:1.55}.dockm-foot{padding-top:12px;font-size:11px}.dockm-foot-sw{width:100%;margin-left:0;justify-content:space-between}.dock-sw{width:44px;height:26px}.dock-sw::after{top:3px;left:3px;width:18px;height:18px}.dock-sw.on::after{transform:translateX(18px)}.dockh-grid{grid-template-columns:1fr;gap:10px}.dockh-card{padding:12px}.dockh-desc{font-size:13px}.dockh-go{font-size:12px}}",
15086
+ "@media (max-width:680px){.dockm-backdrop{align-items:stretch;justify-content:stretch;background:var(--dsw-alias-bg-layer-2);backdrop-filter:none}.dockm-dialog,.dockm-dialog.dockm-max{position:fixed!important;left:0!important;top:0!important;right:auto!important;bottom:auto!important;width:100dvw!important;height:100dvh!important;min-height:100dvh;border:0;border-radius:0;box-shadow:none}.dockm-dialog.dockm-min .dockm-body{display:flex}.dockm-head{min-height:60px;box-sizing:border-box;padding:calc(env(safe-area-inset-top) + 8px) 12px 8px;cursor:default;touch-action:manipulation}.dockm-sub,.dockm-win,.dockm-resize{display:none}.dockm-title{font-size:16px}.dockm-close{width:44px;height:44px;font-size:17px}.dockm-body{flex-direction:column;min-height:0}.dockm-nav{box-sizing:border-box;width:auto;max-width:100%;min-height:56px;flex-direction:row;gap:6px;padding:6px 10px;overflow-x:auto;overflow-y:hidden;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l1);scrollbar-width:none;overscroll-behavior-x:contain}.dockm-nav::-webkit-scrollbar{display:none}.dockm-nav-item{flex:none;min-height:44px;padding:0 12px;font-size:13px;touch-action:manipulation}.dockm-nav-item .dockm-badge{display:none}.dockm-content{padding:16px max(16px,env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left));gap:14px;overscroll-behavior:contain}.dockm-content-head{gap:5px}.dockm-name{font-size:16px}.dockm-desc{font-size:13px;line-height:1.55}.dockm-foot{padding-top:12px;font-size:11px}.dockm-foot-sw{width:100%;margin-left:0;justify-content:space-between}.dock-sw{width:44px;height:26px}.dock-sw::after{top:3px;left:3px;width:18px;height:18px}.dock-sw.on::after{transform:translateX(18px)}.dockh-grid{grid-template-columns:minmax(0,1fr);gap:10px;min-width:0}.dockh-card{padding:12px;box-sizing:border-box;min-width:0}.dockh-desc{font-size:13px}.dockh-go{font-size:12px}}",
15087
+ /* 手机端:功能坞弹层挂在 .overlayLayer(z20) 内,会被 z71 的侧栏抽屉盖住(只剩右侧一条)。\n 把 overlayLayer 在窄屏抬到抽屉之上,面板才能全屏覆盖——且不依赖【手机适配】模块是否启用。 */
15088
+ '@media (max-width:767px){[class*="overlayLayer"]{z-index:100 !important}}',
15089
+ /* 手机:输入卡里的「轮/步/token/缓存」状态条移到输入框上方,压成一行不溢出;空会话时把输入卡贴底 */
15090
+ '@media (max-width:767px){[class*="scrollBody"]>[class*="composerSeat"]{margin-top:auto!important;padding-bottom:0!important}[class*="composerSeat"] [class*="_dock"]{order:-1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0 2px 6px!important;gap:6px!important;font-size:10px!important;overflow:hidden!important}[class*="composerSeat"] [class*="_dock"]>*{min-width:0}}',
14353
15091
  "@media (prefers-reduced-motion:reduce){.dockm-backdrop,.dockm-dialog{animation:none}.dockm-nav-item,.dockm-close,.dockm-win,.dock-sw{transition:none}}",
14354
15092
  ".dockh-desc{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;}",
14355
15093
  ".dockh-stat{color:var(--dsw-alias-label-tertiary);font-size:12px;border-top:1px solid var(--dsw-alias-border-l1);padding-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
@@ -14375,7 +15113,9 @@ var SHELL_CSS = [
14375
15113
  ".dockchip > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}",
14376
15114
  ".dockchip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
14377
15115
  ".dockchip .dockchip-dot{width:6px;height:6px;border-radius:50%;flex:none;}",
14378
- ".dockchip.err{color:var(--dsw-alias-state-error-primary);}"
15116
+ ".dockchip.err{color:var(--dsw-alias-state-error-primary);}",
15117
+ /* 手机:输入区工具行很窄,给 chips 稍多宽度,并隐藏费用等次要后缀(.dockchip-x),避免被截成「⛁ 2…/余…」 */
15118
+ "@media (max-width:767px){.dockchip-row{max-width:min(216px,40cqw)}.dockchip-x{display:none}.dockchip{font-size:10px!important;padding:1px 2px!important;gap:3px!important}.dockchip .dockchip-dot{width:4px;height:4px}.dockchip-ic{display:none}.dockchip-pre{display:none}}"
14379
15119
  ].join("\n");
14380
15120
  var dockCssTag = null;
14381
15121
  var initialCssSchedule = null;
@@ -14411,8 +15151,8 @@ function ensureCss() {
14411
15151
  }
14412
15152
  }
14413
15153
  function useExternalVersion() {
14414
- const [, bump] = import_react24.default.useReducer((n) => n + 1, 0);
14415
- import_react24.default.useEffect(() => {
15154
+ const [, bump] = import_react26.default.useReducer((n) => n + 1, 0);
15155
+ import_react26.default.useEffect(() => {
14416
15156
  externalListeners.add(bump);
14417
15157
  return () => {
14418
15158
  externalListeners.delete(bump);
@@ -14422,44 +15162,31 @@ function useExternalVersion() {
14422
15162
  var lastGeom = { x: null, y: null, w: null, h: null };
14423
15163
  function DockIcon(props) {
14424
15164
  const size = props && props.size || 16;
14425
- return import_react24.default.createElement(
15165
+ return import_react26.default.createElement(
14426
15166
  "svg",
14427
15167
  { width: size, height: size, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
14428
- import_react24.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
14429
- import_react24.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
14430
- import_react24.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
14431
- import_react24.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
15168
+ import_react26.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
15169
+ import_react26.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
15170
+ import_react26.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
15171
+ import_react26.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
14432
15172
  );
14433
15173
  }
14434
- function DockEntry(props) {
14435
- const wide = !!props.wide;
14436
- const [open, setOpen] = import_react24.default.useState(panelNav.open);
14437
- import_react24.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
14438
- return import_react24.default.createElement("button", {
14439
- type: "button",
14440
- className: "docke2-btn" + (open ? " docke2-on" : "") + (wide ? "" : " docke2-rail"),
14441
- title: "\u529F\u80FD\u575E",
14442
- "aria-label": "\u529F\u80FD\u575E",
14443
- "aria-expanded": open,
14444
- onClick: () => setPanelOpen(!open)
14445
- }, import_react24.default.createElement(DockIcon, { size: wide ? 16 : 18 }), wide ? import_react24.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
14446
- }
14447
15174
  function DockModal() {
14448
- const [nav, setNav] = import_react24.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
14449
- import_react24.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
15175
+ const [nav, setNav] = import_react26.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
15176
+ import_react26.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
14450
15177
  const open = nav.open || typeof document === "undefined";
14451
15178
  const active = nav.active;
14452
15179
  const setActive = navigatePanel;
14453
15180
  const navParams = nav.params;
14454
- const [, force] = import_react24.default.useReducer((n) => n + 1, 0);
15181
+ const [, force] = import_react26.default.useReducer((n) => n + 1, 0);
14455
15182
  useExternalVersion();
14456
- const [win, setWin] = import_react24.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
14457
- const dlgRef = import_react24.default.useRef(null);
14458
- const contentRef = import_react24.default.useRef(null);
14459
- import_react24.default.useEffect(() => {
15183
+ const [win, setWin] = import_react26.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
15184
+ const dlgRef = import_react26.default.useRef(null);
15185
+ const contentRef = import_react26.default.useRef(null);
15186
+ import_react26.default.useEffect(() => {
14460
15187
  if (lastGeom.w) setWin({ mode: "normal", x: lastGeom.x, y: lastGeom.y, w: lastGeom.w, h: lastGeom.h });
14461
15188
  }, []);
14462
- import_react24.default.useEffect(() => {
15189
+ import_react26.default.useEffect(() => {
14463
15190
  if (open && contentRef.current) contentRef.current.scrollTop = 0;
14464
15191
  }, [active, open]);
14465
15192
  function beginDrag(e, type) {
@@ -14497,13 +15224,13 @@ function DockModal() {
14497
15224
  const mod = isHome ? null : MODULES.find((m) => m.id === active) || MODULES[0];
14498
15225
  const st = mod ? stateOf(mod.id) : null;
14499
15226
  const View = mod ? mod.View : null;
14500
- const viewNode = mod && View ? import_react24.default.createElement(
15227
+ const viewNode = mod && View ? import_react26.default.createElement(
14501
15228
  "div",
14502
15229
  { className: "dockm-view" },
14503
- import_react24.default.createElement(
15230
+ import_react26.default.createElement(
14504
15231
  FeatureBoundary,
14505
15232
  { key: mod.id, label: mod.name },
14506
- import_react24.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
15233
+ import_react26.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
14507
15234
  )
14508
15235
  ) : null;
14509
15236
  const enabledCount = MODULES.filter((m) => {
@@ -14517,10 +15244,10 @@ function DockModal() {
14517
15244
  width: win.w != null ? win.w : void 0,
14518
15245
  height: win.mode === "min" ? "auto" : win.h != null ? win.h : void 0
14519
15246
  } : null;
14520
- return import_react24.default.createElement(
15247
+ return import_react26.default.createElement(
14521
15248
  "div",
14522
15249
  { className: "dockm-backdrop", onClick: () => setPanelOpen(false) },
14523
- import_react24.default.createElement(
15250
+ import_react26.default.createElement(
14524
15251
  "div",
14525
15252
  {
14526
15253
  className: "dockm-dialog" + (win.mode === "max" ? " dockm-max" : "") + (win.mode === "min" ? " dockm-min" : ""),
@@ -14528,41 +15255,41 @@ function DockModal() {
14528
15255
  ref: dlgRef,
14529
15256
  onClick: (e) => e.stopPropagation()
14530
15257
  },
14531
- import_react24.default.createElement(
15258
+ import_react26.default.createElement(
14532
15259
  "div",
14533
15260
  {
14534
15261
  className: "dockm-head",
14535
15262
  onPointerDown: (e) => beginDrag(e, "move"),
14536
15263
  onDoubleClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
14537
15264
  },
14538
- import_react24.default.createElement(DockIcon, null),
14539
- import_react24.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
14540
- import_react24.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
14541
- import_react24.default.createElement(
15265
+ import_react26.default.createElement(DockIcon, null),
15266
+ import_react26.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
15267
+ import_react26.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
15268
+ import_react26.default.createElement(
14542
15269
  "span",
14543
15270
  { className: "dockm-ctrls" },
14544
- import_react24.default.createElement("button", {
15271
+ import_react26.default.createElement("button", {
14545
15272
  type: "button",
14546
15273
  className: "dockm-win",
14547
15274
  title: win.mode === "min" ? "\u8FD8\u539F" : "\u6700\u5C0F\u5316",
14548
15275
  onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "min" ? "normal" : "min" }))
14549
15276
  }, "\u2581"),
14550
- import_react24.default.createElement("button", {
15277
+ import_react26.default.createElement("button", {
14551
15278
  type: "button",
14552
15279
  className: "dockm-win",
14553
15280
  title: win.mode === "max" ? "\u8FD8\u539F" : "\u6700\u5927\u5316",
14554
15281
  onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
14555
15282
  }, win.mode === "max" ? "\u2750" : "\u25A2"),
14556
- import_react24.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
15283
+ import_react26.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
14557
15284
  )
14558
15285
  ),
14559
- import_react24.default.createElement(
15286
+ import_react26.default.createElement(
14560
15287
  "div",
14561
15288
  { className: "dockm-body" },
14562
- import_react24.default.createElement(
15289
+ import_react26.default.createElement(
14563
15290
  "nav",
14564
15291
  { className: "dockm-nav", "aria-label": "\u529F\u80FD\u6A21\u5757" },
14565
- import_react24.default.createElement(
15292
+ import_react26.default.createElement(
14566
15293
  "button",
14567
15294
  {
14568
15295
  type: "button",
@@ -14570,10 +15297,10 @@ function DockModal() {
14570
15297
  className: "dockm-nav-item" + (isHome ? " on" : ""),
14571
15298
  onClick: () => setActive("home")
14572
15299
  },
14573
- import_react24.default.createElement("span", { className: "dockm-navhome" }, import_react24.default.createElement(DockIcon, null)),
14574
- import_react24.default.createElement("span", null, "\u9996\u9875")
15300
+ import_react26.default.createElement("span", { className: "dockm-navhome" }, import_react26.default.createElement(DockIcon, null)),
15301
+ import_react26.default.createElement("span", null, "\u9996\u9875")
14575
15302
  ),
14576
- MODULES.map((m) => import_react24.default.createElement(
15303
+ MODULES.map((m) => import_react26.default.createElement(
14577
15304
  "button",
14578
15305
  {
14579
15306
  type: "button",
@@ -14581,42 +15308,42 @@ function DockModal() {
14581
15308
  className: "dockm-nav-item" + (m.id === active ? " on" : ""),
14582
15309
  onClick: () => setActive(m.id)
14583
15310
  },
14584
- import_react24.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
14585
- import_react24.default.createElement("span", null, m.name),
14586
- m.planned ? import_react24.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
14587
- m.external ? import_react24.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
15311
+ import_react26.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
15312
+ import_react26.default.createElement("span", null, m.name),
15313
+ m.planned ? import_react26.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
15314
+ m.external ? import_react26.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
14588
15315
  ))
14589
15316
  ),
14590
- import_react24.default.createElement(
15317
+ import_react26.default.createElement(
14591
15318
  "div",
14592
15319
  { className: "dockm-content", ref: contentRef },
14593
- import_react24.default.createElement(
15320
+ import_react26.default.createElement(
14594
15321
  "div",
14595
15322
  { className: "dockm-content-head" },
14596
- import_react24.default.createElement(
15323
+ import_react26.default.createElement(
14597
15324
  "div",
14598
15325
  { className: "dockm-name" },
14599
- isHome ? import_react24.default.createElement("span", { className: "dockm-navhome" }, import_react24.default.createElement(DockIcon, null)) : import_react24.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
15326
+ isHome ? import_react26.default.createElement("span", { className: "dockm-navhome" }, import_react26.default.createElement(DockIcon, null)) : import_react26.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
14600
15327
  isHome ? "\u9996\u9875" : mod.name,
14601
- !isHome && mod.planned ? import_react24.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
14602
- !isHome && mod.external ? import_react24.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
15328
+ !isHome && mod.planned ? import_react26.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
15329
+ !isHome && mod.external ? import_react26.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
14603
15330
  ),
14604
- import_react24.default.createElement(
15331
+ import_react26.default.createElement(
14605
15332
  "div",
14606
15333
  { className: "dockm-desc" },
14607
15334
  isHome ? "\u6240\u6709\u5B50\u529F\u80FD\u603B\u63FD\uFF1A\u8FD0\u884C\u72B6\u6001\u3001\u6982\u8981\u4E0E\u5FEB\u6377\u5F00\u5173\uFF0C\u70B9\u51FB\u5361\u7247\u8FDB\u5165\u5BF9\u5E94\u529F\u80FD\u9875\u3002" : mod.description
14608
15335
  )
14609
15336
  ),
14610
- isHome ? import_react24.default.createElement("div", { className: "dockm-view" }, import_react24.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react24.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react24.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react24.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
14611
- import_react24.default.createElement(
15337
+ isHome ? import_react26.default.createElement("div", { className: "dockm-view" }, import_react26.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react26.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react26.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react26.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
15338
+ import_react26.default.createElement(
14612
15339
  "div",
14613
15340
  { className: "dockm-foot" },
14614
- import_react24.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
14615
- !isHome && mod && !mod.planned && st ? import_react24.default.createElement(
15341
+ import_react26.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
15342
+ !isHome && mod && !mod.planned && st ? import_react26.default.createElement(
14616
15343
  "span",
14617
15344
  { className: "dockm-foot-sw" },
14618
- import_react24.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
14619
- import_react24.default.createElement("button", {
15345
+ import_react26.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
15346
+ import_react26.default.createElement("button", {
14620
15347
  type: "button",
14621
15348
  className: "dock-sw" + (st.enabled ? " on" : ""),
14622
15349
  role: "switch",
@@ -14629,11 +15356,11 @@ function DockModal() {
14629
15356
  }
14630
15357
  })
14631
15358
  ) : null,
14632
- !isHome && mod && typeof mod.Chip === "function" ? import_react24.default.createElement(
15359
+ !isHome && mod && typeof mod.Chip === "function" ? import_react26.default.createElement(
14633
15360
  "span",
14634
15361
  { className: "dockm-foot-sw" },
14635
- import_react24.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
14636
- import_react24.default.createElement("button", {
15362
+ import_react26.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
15363
+ import_react26.default.createElement("button", {
14637
15364
  type: "button",
14638
15365
  className: "dock-sw" + (chipShown(mod.id) ? " on" : ""),
14639
15366
  role: "switch",
@@ -14649,30 +15376,30 @@ function DockModal() {
14649
15376
  )
14650
15377
  )
14651
15378
  ),
14652
- win.mode === "normal" ? import_react24.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
15379
+ win.mode === "normal" ? import_react26.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
14653
15380
  )
14654
15381
  );
14655
15382
  }
14656
15383
  function HomeView(props) {
14657
15384
  const ctx = props && props.ctx;
14658
- const [, force] = import_react24.default.useReducer((n) => n + 1, 0);
15385
+ const [, force] = import_react26.default.useReducer((n) => n + 1, 0);
14659
15386
  useExternalVersion();
14660
15387
  const open = (id) => {
14661
15388
  if (props && typeof props.onOpen === "function") props.onOpen(id);
14662
15389
  };
14663
- return import_react24.default.createElement(
15390
+ return import_react26.default.createElement(
14664
15391
  "div",
14665
15392
  { className: "dockh-grid" },
14666
15393
  allModules().map((m) => {
14667
15394
  const st = stateOf(m.id);
14668
15395
  const enabled = !!(st && st.enabled);
14669
15396
  const Stat = m.HomeStat;
14670
- const statNode = m.planned ? import_react24.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react24.default.createElement(
15397
+ const statNode = m.planned ? import_react26.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react26.default.createElement(
14671
15398
  FeatureBoundary,
14672
15399
  { key: m.id, label: m.name },
14673
- import_react24.default.createElement(Stat, { ctx })
14674
- ) : import_react24.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
14675
- return import_react24.default.createElement(
15400
+ import_react26.default.createElement(Stat, { ctx })
15401
+ ) : import_react26.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
15402
+ return import_react26.default.createElement(
14676
15403
  "div",
14677
15404
  {
14678
15405
  key: m.id,
@@ -14687,21 +15414,21 @@ function HomeView(props) {
14687
15414
  }
14688
15415
  }
14689
15416
  },
14690
- import_react24.default.createElement(
15417
+ import_react26.default.createElement(
14691
15418
  "div",
14692
15419
  { className: "dockh-head" },
14693
- import_react24.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
14694
- import_react24.default.createElement("span", { className: "dockh-name" }, m.name),
14695
- m.external ? import_react24.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
15420
+ import_react26.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
15421
+ import_react26.default.createElement("span", { className: "dockh-name" }, m.name),
15422
+ m.external ? import_react26.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
14696
15423
  // 状态标识:圆点 + 文字(纯展示,与开关视觉区分)
14697
- import_react24.default.createElement(
15424
+ import_react26.default.createElement(
14698
15425
  "span",
14699
15426
  { className: "dockh-status" + (m.planned ? " plan" : enabled ? "" : " off") },
14700
- import_react24.default.createElement("span", { className: "dockh-sdot" }),
14701
- import_react24.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
15427
+ import_react26.default.createElement("span", { className: "dockh-sdot" }),
15428
+ import_react26.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
14702
15429
  ),
14703
15430
  // 启停开关(规划中的功能不显示)
14704
- m.planned ? null : import_react24.default.createElement("button", {
15431
+ m.planned ? null : import_react26.default.createElement("button", {
14705
15432
  type: "button",
14706
15433
  className: "dock-sw" + (enabled ? " on" : ""),
14707
15434
  role: "switch",
@@ -14716,12 +15443,12 @@ function HomeView(props) {
14716
15443
  }
14717
15444
  })
14718
15445
  ),
14719
- import_react24.default.createElement("div", { className: "dockh-desc" }, m.description),
14720
- import_react24.default.createElement("div", { className: "dockh-stat" }, statNode),
14721
- import_react24.default.createElement(
15446
+ import_react26.default.createElement("div", { className: "dockh-desc" }, m.description),
15447
+ import_react26.default.createElement("div", { className: "dockh-stat" }, statNode),
15448
+ import_react26.default.createElement(
14722
15449
  "div",
14723
15450
  { className: "dockh-foot" },
14724
- import_react24.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
15451
+ import_react26.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
14725
15452
  )
14726
15453
  );
14727
15454
  })
@@ -14729,16 +15456,16 @@ function HomeView(props) {
14729
15456
  }
14730
15457
  function DockPanel(props) {
14731
15458
  const ctx = ctxRef.current;
14732
- const [, force] = import_react24.default.useReducer((n) => n + 1, 0);
15459
+ const [, force] = import_react26.default.useReducer((n) => n + 1, 0);
14733
15460
  useExternalVersion();
14734
15461
  const toggle = (id) => {
14735
15462
  toggleFeature(id);
14736
15463
  force();
14737
15464
  };
14738
- return import_react24.default.createElement(
15465
+ return import_react26.default.createElement(
14739
15466
  "div",
14740
15467
  { className: "dock-root" },
14741
- import_react24.default.createElement(
15468
+ import_react26.default.createElement(
14742
15469
  "div",
14743
15470
  { className: "dock-intro" },
14744
15471
  "\u529F\u80FD\u575E\uFF08dsh-dock\uFF09\xB7 \u6240\u6709\u5C0F\u529F\u80FD\u96C6\u4E2D\u5728\u8FD9\u4E00\u4E2A\u9762\u677F\u91CC\u7BA1\u7406\u3002v0.4.0 \u8D77\u6BCF\u4E2A\u529F\u80FD\u662F\u72EC\u7ACB\u6A21\u5757\uFF08features/<id>/\uFF09\uFF0C",
@@ -14747,25 +15474,25 @@ function DockPanel(props) {
14747
15474
  allModules().map((f) => {
14748
15475
  const st = stateOf(f.id);
14749
15476
  const View = f.View;
14750
- const viewNode = !f.planned && st.enabled && View ? import_react24.default.createElement(
15477
+ const viewNode = !f.planned && st.enabled && View ? import_react26.default.createElement(
14751
15478
  "div",
14752
15479
  { className: "dock-body" },
14753
- import_react24.default.createElement(
15480
+ import_react26.default.createElement(
14754
15481
  FeatureBoundary,
14755
15482
  { key: f.id, label: f.name },
14756
- import_react24.default.createElement(View, { ctx, feature: f, params: props && props.params })
15483
+ import_react26.default.createElement(View, { ctx, feature: f, params: props && props.params })
14757
15484
  )
14758
15485
  ) : null;
14759
- return import_react24.default.createElement(
15486
+ return import_react26.default.createElement(
14760
15487
  "div",
14761
15488
  { className: "dock-card", key: f.id },
14762
- import_react24.default.createElement(
15489
+ import_react26.default.createElement(
14763
15490
  "div",
14764
15491
  { className: "dock-card-head" },
14765
- import_react24.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
14766
- import_react24.default.createElement("span", { className: "dock-name" }, f.name),
14767
- import_react24.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
14768
- f.planned ? import_react24.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react24.default.createElement("button", {
15492
+ import_react26.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
15493
+ import_react26.default.createElement("span", { className: "dock-name" }, f.name),
15494
+ import_react26.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
15495
+ f.planned ? import_react26.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react26.default.createElement("button", {
14769
15496
  type: "button",
14770
15497
  className: "dock-sw" + (st.enabled ? " on" : ""),
14771
15498
  role: "switch",
@@ -14774,11 +15501,11 @@ function DockPanel(props) {
14774
15501
  title: st.enabled ? "\u505C\u7528\u300C" + f.name + "\u300D" : "\u542F\u7528\u300C" + f.name + "\u300D",
14775
15502
  onClick: () => toggle(f.id)
14776
15503
  }),
14777
- !f.planned && typeof f.Chip === "function" ? import_react24.default.createElement(
15504
+ !f.planned && typeof f.Chip === "function" ? import_react26.default.createElement(
14778
15505
  "span",
14779
15506
  { className: "dockm-foot-sw" },
14780
- import_react24.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
14781
- import_react24.default.createElement("button", {
15507
+ import_react26.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
15508
+ import_react26.default.createElement("button", {
14782
15509
  type: "button",
14783
15510
  className: "dock-sw" + (chipShown(f.id) ? " on" : ""),
14784
15511
  role: "switch",
@@ -14792,22 +15519,40 @@ function DockPanel(props) {
14792
15519
  })
14793
15520
  ) : null
14794
15521
  ),
14795
- f.planned ? import_react24.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react24.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
15522
+ f.planned ? import_react26.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react26.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
14796
15523
  viewNode
14797
15524
  );
14798
15525
  })
14799
15526
  );
14800
15527
  }
15528
+ function DockPage() {
15529
+ return import_react26.default.createElement(
15530
+ "div",
15531
+ { className: "dockm-page" },
15532
+ import_react26.default.createElement(
15533
+ "div",
15534
+ { className: "dockm-page-head" },
15535
+ import_react26.default.createElement("span", { className: "dockm-page-icon" }, import_react26.default.createElement(DockIcon, { size: 20 })),
15536
+ import_react26.default.createElement(
15537
+ "div",
15538
+ { className: "dockm-page-titles" },
15539
+ import_react26.default.createElement("div", { className: "dockm-page-title" }, "\u529F\u80FD\u575E"),
15540
+ import_react26.default.createElement("div", { className: "dockm-page-sub" }, "\u6240\u6709\u5C0F\u529F\u80FD\u96C6\u4E2D\u5728\u8FD9\u91CC\u7BA1\u7406\u3002\u4FA7\u680F\u56FE\u6807\u53EF\u5728\u300C\u66F4\u591A\u300D\u83DC\u5355\u91CC Pin \u5230\u9876\u90E8\uFF0C\u6216\u53D6\u6D88\u56FA\u5B9A\u6536\u8FDB\u66F4\u591A\u3002")
15541
+ )
15542
+ ),
15543
+ import_react26.default.createElement("div", { className: "dockm-page-body" }, import_react26.default.createElement(DockPanel, { params: null }))
15544
+ );
15545
+ }
14801
15546
  function DockChips(props) {
14802
- const [, force] = import_react24.default.useReducer((n) => n + 1, 0);
14803
- import_react24.default.useEffect(() => subscribeFeatureState(() => force()), []);
15547
+ const [, force] = import_react26.default.useReducer((n) => n + 1, 0);
15548
+ import_react26.default.useEffect(() => subscribeFeatureState(() => force()), []);
14804
15549
  const items = [];
14805
15550
  for (const f of allModules()) {
14806
15551
  if (f.planned || !stateOf(f.id).enabled || !chipShown(f.id) || typeof f.Chip !== "function") continue;
14807
- items.push(import_react24.default.createElement(
15552
+ items.push(import_react26.default.createElement(
14808
15553
  FeatureBoundary,
14809
15554
  { key: f.id, label: f.name },
14810
- import_react24.default.createElement(f.Chip, {
15555
+ import_react26.default.createElement(f.Chip, {
14811
15556
  ctx: props.ctx,
14812
15557
  feature: f,
14813
15558
  session: props.session,
@@ -14817,38 +15562,38 @@ function DockChips(props) {
14817
15562
  ));
14818
15563
  }
14819
15564
  if (items.length === 0) return null;
14820
- return import_react24.default.createElement("div", { className: "dockchip-row" }, items);
15565
+ return import_react26.default.createElement("div", { className: "dockchip-row" }, items);
14821
15566
  }
14822
15567
  function FeatureOverlays() {
14823
- const [, force] = import_react24.default.useReducer((n) => n + 1, 0);
15568
+ const [, force] = import_react26.default.useReducer((n) => n + 1, 0);
14824
15569
  useExternalVersion();
14825
- import_react24.default.useEffect(() => subscribeFeatureState(() => force()), []);
15570
+ import_react26.default.useEffect(() => subscribeFeatureState(() => force()), []);
14826
15571
  const items = [];
14827
15572
  for (const f of allModules()) {
14828
15573
  if (f.planned || !stateOf(f.id).enabled || typeof f.Overlay !== "function") continue;
14829
- items.push(import_react24.default.createElement(
15574
+ items.push(import_react26.default.createElement(
14830
15575
  FeatureBoundary,
14831
15576
  { key: f.id, label: f.name },
14832
- import_react24.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
15577
+ import_react26.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
14833
15578
  ));
14834
15579
  }
14835
15580
  if (items.length === 0) return null;
14836
- return import_react24.default.createElement(import_react24.default.Fragment, null, items);
15581
+ return import_react26.default.createElement(import_react26.default.Fragment, null, items);
14837
15582
  }
14838
15583
  function FeatureTurnTail(props) {
14839
- const [, force] = import_react24.default.useReducer((n) => n + 1, 0);
14840
- import_react24.default.useEffect(() => subscribeFeatureState(() => force()), []);
15584
+ const [, force] = import_react26.default.useReducer((n) => n + 1, 0);
15585
+ import_react26.default.useEffect(() => subscribeFeatureState(() => force()), []);
14841
15586
  const items = [];
14842
15587
  for (const f of allModules()) {
14843
15588
  if (f.planned || !stateOf(f.id).enabled || typeof f.TurnTail !== "function") continue;
14844
- items.push(import_react24.default.createElement(
15589
+ items.push(import_react26.default.createElement(
14845
15590
  FeatureBoundary,
14846
15591
  { key: f.id, label: f.name },
14847
- import_react24.default.createElement(f.TurnTail, Object.assign({}, props, { ctx: ctxRef.current, feature: f }))
15592
+ import_react26.default.createElement(f.TurnTail, Object.assign({}, props, { ctx: ctxRef.current, feature: f }))
14848
15593
  ));
14849
15594
  }
14850
15595
  if (items.length === 0) return null;
14851
- return import_react24.default.createElement(import_react24.default.Fragment, null, items);
15596
+ return import_react26.default.createElement(import_react26.default.Fragment, null, items);
14852
15597
  }
14853
15598
  var ctxRef = { current: null };
14854
15599
  function apply(ctx) {
@@ -14857,29 +15602,33 @@ function apply(ctx) {
14857
15602
  initFeatureState(BUILTIN_FEATURES.concat(PLANNED_FEATURES));
14858
15603
  const slots = ctx.get("slots");
14859
15604
  if (slots === void 0) return;
14860
- slots.inject("sidebar.footer.action", () => slots.register(
14861
- { name: "sidebar.footer.action", id: "dsh-dock", order: 1, label: "\u529F\u80FD\u575E" },
14862
- (props) => import_react24.default.createElement(DockEntry, props)
15605
+ slots.inject("sidebar.panellist", () => slots.register(
15606
+ { name: "sidebar.panellist", id: "dsh-dock", order: 30, label: "\u529F\u80FD\u575E" },
15607
+ (props) => import_react26.default.createElement(DockIcon, { size: props && props.size || 18 })
15608
+ ));
15609
+ slots.inject("main", () => slots.register(
15610
+ { name: "main", key: "dsh-dock", label: "\u529F\u80FD\u575E" },
15611
+ () => import_react26.default.createElement(DockPage, null)
14863
15612
  ));
14864
15613
  slots.inject("shell.overlay", () => slots.register(
14865
15614
  { name: "shell.overlay", id: "dsh-dock-panel", order: 21, label: "\u529F\u80FD\u575E\u9762\u677F" },
14866
- () => import_react24.default.createElement(DockModal, null)
15615
+ () => import_react26.default.createElement(DockModal, null)
14867
15616
  ));
14868
15617
  slots.inject("shell.overlay", () => slots.register(
14869
15618
  { name: "shell.overlay", id: "dsh-dock-feature-overlays", order: 22, label: "\u529F\u80FD\u575E\u5168\u5C40\u6D6E\u5C42" },
14870
- () => import_react24.default.createElement(FeatureOverlays, null)
15619
+ () => import_react26.default.createElement(FeatureOverlays, null)
14871
15620
  ));
14872
15621
  slots.inject("settings.section", () => slots.register(
14873
15622
  { name: "settings.section", id: "dsh-dock", order: 90, label: "\u529F\u80FD\u575E" },
14874
- (props) => import_react24.default.createElement(DockPanel, props)
15623
+ (props) => import_react26.default.createElement(DockPanel, props)
14875
15624
  ));
14876
15625
  slots.inject("conversation.input.left", () => slots.register(
14877
15626
  { name: "conversation.input.left", id: "dsh-dock-chips", order: 10, label: "\u529F\u80FD\u575E" },
14878
- (zone) => import_react24.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
15627
+ (zone) => import_react26.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
14879
15628
  ));
14880
15629
  slots.inject("conversation.chat.turnTail", () => slots.register(
14881
15630
  { name: "conversation.chat.turnTail", id: "dsh-dock-turn-tail", order: 40, label: "\u529F\u80FD\u575E" },
14882
- (owner) => import_react24.default.createElement(FeatureTurnTail, owner)
15631
+ (owner) => import_react26.default.createElement(FeatureTurnTail, owner)
14883
15632
  ));
14884
15633
  }
14885
15634
  var inject = ["timer"];