dsh-schedule-ilife 0.3.13 → 0.3.15

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/dist/client.js CHANGED
@@ -43,9 +43,12 @@ window.__ModuleLoader__.load({
43
43
  const RPC_ENDPOINT_CONFIG_GET = "config.get";
44
44
  const RPC_ENDPOINT_CONFIG_SAVE = "config.save";
45
45
  const RPC_ENDPOINT_CONFIG_RESET = "config.reset";
46
- /** 高级组标题与副文案(六家逐字相同,收在这里一处)。 */
46
+ /** 高级组标题(六家逐字相同,收在这里一处)。
47
+ *
48
+ * #934:原先还有一条副文案 `ADVANCED_GROUP_NOTE`(「不常改。留空=用默认值。」),
49
+ * 维护者裁定**整条删除、删后不另找地方说**——理由:三家高级项全是只读行、不参与保存、根本没有"留空",
50
+ * 而"留空会怎样"这条口径本就逐行住在每条的 `hint` 里(见本件 `ConfigItem.hint` 的契约)。 */
47
51
  const ADVANCED_GROUP_TITLE = "高级";
48
- const ADVANCED_GROUP_NOTE = "不常改。留空=用默认值。";
49
52
  /** 请求超时毫秒:与宿主侧 SPAWN_TIMEOUT_MS 同级,界面永不无限转圈。 */
50
53
  const READ_TIMEOUT_MS$1 = 2e4;
51
54
  /** 复制那一枚按钮就地变「已复制」之后,多久变回「复制」(定稿 v3 第三条:1.5 秒,不弹提示)。 */
@@ -832,7 +835,7 @@ window.__ModuleLoader__.load({
832
835
  textOverflow: "ellipsis",
833
836
  whiteSpace: "nowrap"
834
837
  },
835
- error: { color: "var(--dsw-alias-label-error, #e66)" }
838
+ error: { color: "var(--dsw-alias-state-error-primary, #e66)" }
836
839
  };
837
840
  /** 面包屑:从文件系统根到当前层,每一格都是跳转目标(`listing.crumbs` 由取数方给)。 */
838
841
  function crumbRow(state, onEnter) {
@@ -1087,6 +1090,23 @@ window.__ModuleLoader__.load({
1087
1090
  * 键名一个都不许改:六家附加块真消费 `okText`/`error`/`rows`/`label`/`muted`/`hint`/`info`/
1088
1091
  * `bar`/`btn` 这九格(`plugin-memo-ilife/src/client.ts`、`plugin-schedule-ilife/src/client.ts` 的
1089
1092
  * `PanelStyleSlots`),跨包锁另钉 `card`/`input`/`btnPrimary`/`btnPick`/`summary`/`title`/`version`。 */
1093
+ /** #941/丁:**浅色档距自合成**——宿主在浅色下四层底同白(`bg-base = bg-layer-1/2/3`),
1094
+ * 拿不到可用的层级差,所以三处面(卡描边/沉底盒底/输入框描边)由我们自己按墨色派生。
1095
+ *
1096
+ * 取 `label-primary` 当墨色分母:浅色下它是近黑、深色下它是近白 ⇒ **同一条表达式两套主题都成立**
1097
+ * (浅色补出可用的档距,深色退化成今天那几档观感)。百分比来自维护者选定的方案丁:
1098
+ * 卡描边 19%/沉底盒底 9%/输入框描边 24%/骨架条 21%。这是本仓第一处"自定值",属真源增补
1099
+ * (v3.1 只有深色一套 token,从未覆盖浅色)。 */
1100
+ const PANEL_INK = "var(--dsw-alias-label-primary, #f9fafb)";
1101
+ const inkMix = (percent, into) => into === void 0 ? `color-mix(in srgb, ${PANEL_INK} ${percent}%, transparent)` : `color-mix(in srgb, ${PANEL_INK} ${percent}%, ${into})`;
1102
+ /** 卡片描边:浅色 ≈`#cfcfcf` ⇔ 深色 ≈`#4a4b4d`。 */
1103
+ const PANEL_CARD_EDGE = inkMix(19);
1104
+ /** 沉底盒底(母版行/高级组体/状态行):浅色 ≈`#e9e9e9` ⇔ 深色 ≈`#3a3b3d`。 */
1105
+ const PANEL_SUNKEN_FILL = inkMix(9, "var(--dsw-alias-bg-layer-1, #232324)");
1106
+ /** 输入框描边:浅色 ≈`#c4c4c4` ⇔ 深色 ≈`#5a5b5d`。 */
1107
+ const PANEL_FIELD_EDGE = inkMix(24);
1108
+ /** 骨架条:浅色 ≈`#c9ccd2`(1.6:1)⇔ 深色 ≈`#404143`。 */
1109
+ const PANEL_SKELETON_FILL = inkMix(21);
1090
1110
  const S = {
1091
1111
  /** `.ic-card`:`background:var(--ic-surface)`(=bg-layer-1)+`border:1px solid var(--ic-line-strong)`
1092
1112
  * +`border-radius:12px`+`padding:14px`+`box-shadow:inset 0 1px 0 rgba(255,255,255,.06)`。
@@ -1094,7 +1114,7 @@ window.__ModuleLoader__.load({
1094
1114
  card: {
1095
1115
  padding: 14,
1096
1116
  borderRadius: 12,
1097
- border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,.12))",
1117
+ border: "1px solid " + PANEL_CARD_EDGE,
1098
1118
  background: "var(--dsw-alias-bg-layer-1, #232324)",
1099
1119
  color: "var(--dsw-alias-label-primary, #f9fafb)",
1100
1120
  boxShadow: "inset 0 1px 0 rgba(255,255,255,.06)"
@@ -1114,6 +1134,83 @@ window.__ModuleLoader__.load({
1114
1134
  /** `.ic-file{margin-top:4px}` 的那 4px 挂在两行的公共容器上:`info` 自己一格 margin 都不写
1115
1135
  * (#743 ①:头部两行间距不一家一个数,故这一项一律不写 margin)。 */
1116
1136
  fileWrap: { marginTop: 4 },
1137
+ /** #939:骨架条(照真源 `.ic-sk`:`display:block;height:17px;border-radius:4px`)。
1138
+ * 高度按一行正文画——inline-block 跟着父级行高走会让骨架行比填充后的文字行高 4px、六家叠起来就是一片下移。
1139
+ * 底色走派生值(宿主专用骨架档 `bg-skeleton` 在浅色下只有 1.09:1,等于看不见)。 */
1140
+ skeleton: {
1141
+ display: "block",
1142
+ height: 17,
1143
+ borderRadius: 4,
1144
+ background: PANEL_SKELETON_FILL
1145
+ },
1146
+ /** #936:状态行那一块(照真源 `.ic-status`)——沉底面盒子,里面三行:状态行/路径行/官网行。 */
1147
+ statusBox: {
1148
+ marginTop: 11,
1149
+ padding: "10px 12px",
1150
+ background: PANEL_SUNKEN_FILL,
1151
+ border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,.12))",
1152
+ borderRadius: 8
1153
+ },
1154
+ /** `.ic-srow{display:flex;align-items:center;gap:8px;font-size:12px;flex-wrap:wrap}`(12px ⇒ 0.86em)。 */
1155
+ statusRow: {
1156
+ display: "flex",
1157
+ alignItems: "center",
1158
+ gap: 8,
1159
+ fontSize: "0.86em",
1160
+ flexWrap: "wrap"
1161
+ },
1162
+ /** `.ic-dot{width:8px;height:8px;border-radius:50%}`——底色按档位在组件里补。 */
1163
+ statusDot: {
1164
+ width: 8,
1165
+ height: 8,
1166
+ borderRadius: "50%",
1167
+ flex: "0 0 auto"
1168
+ },
1169
+ /** `.ic-sname{font-weight:600;white-space:nowrap}`。 */
1170
+ statusName: {
1171
+ fontWeight: 600,
1172
+ whiteSpace: "nowrap"
1173
+ },
1174
+ /** `.ic-stxt{color:var(--ic-muted);min-width:0}`。 */
1175
+ statusText: {
1176
+ color: "var(--dsw-alias-label-secondary, #cfd3d6)",
1177
+ minWidth: 0
1178
+ },
1179
+ /** `.ic-sfind{display:flex;align-items:center;gap:8px;margin-top:7px}`。 */
1180
+ statusFind: {
1181
+ display: "flex",
1182
+ alignItems: "center",
1183
+ gap: 8,
1184
+ marginTop: 7
1185
+ },
1186
+ /** `.ic-spath{font-size:10.5px;color:var(--ic-faint);white-space:nowrap;overflow:hidden}`
1187
+ * ——单行不折、超出裁掉(**不写省略号**:本件有一条"零省略号"的跨包锁)。
1188
+ * **不写 `fontFamily`**:v3.1 这一格要 `var(--ic-mono)`,但 `#739 ①` 明令共用件零字族(宿主没有界面字族
1189
+ * token,钉死会在别的窗口尺寸上失真)——与真源的同一处已知不同,账在 #920 证据件里。 */
1190
+ statusPath: {
1191
+ fontSize: "0.75em",
1192
+ color: "var(--dsw-alias-label-tertiary, #adb2b8)",
1193
+ minWidth: 0,
1194
+ whiteSpace: "nowrap",
1195
+ overflow: "hidden"
1196
+ },
1197
+ /** `.ic-ver{font-size:10px;border:1px solid var(--ic-line-strong);border-radius:999px;padding:0 6px}`。 */
1198
+ statusVersion: {
1199
+ fontSize: "0.72em",
1200
+ color: "var(--dsw-alias-label-tertiary, #adb2b8)",
1201
+ border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,.12))",
1202
+ borderRadius: 999,
1203
+ padding: "0 6px",
1204
+ whiteSpace: "nowrap"
1205
+ },
1206
+ /** `.ic-url{display:inline-block;margin-top:7px;font-size:10.5px;color:var(--ic-faint)}`
1207
+ * ——字族同样继承宿主(`#739 ①`:共用件零 `fontFamily`),理由同上一格。 */
1208
+ statusUrl: {
1209
+ display: "inline-block",
1210
+ marginTop: 7,
1211
+ fontSize: "0.75em",
1212
+ color: "var(--dsw-alias-label-tertiary, #adb2b8)"
1213
+ },
1117
1214
  /** `.ic-file b{color:var(--ic-faint);font-weight:400;margin-right:5px}`(「配置文件」「数据目录」那两个字)。 */
1118
1215
  fileLabel: {
1119
1216
  color: "var(--dsw-alias-label-tertiary, #adb2b8)",
@@ -1239,7 +1336,7 @@ window.__ModuleLoader__.load({
1239
1336
  /** `.ic-master`:母版行那一块盒子(`--ic-sunken` 底 + `border-radius:8px` + `padding:11px 12px`
1240
1337
  * + `margin-top:11px` + 内高光)。 */
1241
1338
  master: {
1242
- background: "var(--dsw-alias-bg-layer-3, #353638)",
1339
+ background: PANEL_SUNKEN_FILL,
1243
1340
  border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,.12))",
1244
1341
  borderRadius: 8,
1245
1342
  padding: "11px 12px",
@@ -1279,7 +1376,7 @@ window.__ModuleLoader__.load({
1279
1376
  padding: "5px 8px",
1280
1377
  boxSizing: "border-box",
1281
1378
  background: "var(--dsw-alias-bg-base, #151517)",
1282
- border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,.12))",
1379
+ border: "1px solid " + PANEL_FIELD_EDGE,
1283
1380
  borderRadius: 6,
1284
1381
  color: "var(--dsw-alias-label-primary, #f9fafb)"
1285
1382
  },
@@ -1346,18 +1443,13 @@ window.__ModuleLoader__.load({
1346
1443
  },
1347
1444
  /** `.ic-ghead::before{content:'›';color:var(--ic-muted)}`——画成真的那一个字符(内联样式给不出伪元素)。 */
1348
1445
  groupMark: { color: "var(--dsw-alias-label-secondary, #cfd3d6)" },
1349
- /** `.ic-ghead .ic-gnote{color:var(--ic-faint);font-weight:400;font-size:11.5px}`(11.5px ⇒ `0.92em`)。 */
1350
- groupNote: {
1351
- color: "var(--dsw-alias-label-tertiary, #adb2b8)",
1352
- fontWeight: 400,
1353
- fontSize: "0.92em"
1354
- },
1446
+ /** #934:`.ic-gnote` 那条副文案的样式随之删除——副文案本身已按维护者裁定整条撤掉(零消费者的槽位不留)。 */
1355
1447
  /** `.ic-group > .ic-gbody{margin-top:9px;padding:11px 12px;background:var(--ic-sunken);
1356
1448
  * border-radius:8px;box-shadow:inset 0 1px 0 rgba(255,255,255,.04)}`。 */
1357
1449
  groupBody: {
1358
1450
  marginTop: 9,
1359
1451
  padding: "11px 12px",
1360
- background: "var(--dsw-alias-bg-layer-3, #353638)",
1452
+ background: PANEL_SUNKEN_FILL,
1361
1453
  border: "1px solid var(--dsw-alias-border-l2, rgba(255,255,255,.12))",
1362
1454
  borderRadius: 8,
1363
1455
  boxShadow: "inset 0 1px 0 rgba(255,255,255,.04)"
@@ -1413,14 +1505,8 @@ window.__ModuleLoader__.load({
1413
1505
  cursor: "pointer",
1414
1506
  whiteSpace: "nowrap"
1415
1507
  },
1416
- /** 附加块(版本行/状态行)那份字面:`--ic-faint` + `0.92em`(#739 ③ 钉死这一格)。 */
1417
- version: {
1418
- marginTop: 8,
1419
- paddingTop: 8,
1420
- borderTop: "1px dashed var(--dsw-alias-border-l1, rgba(255,255,255,.06))",
1421
- color: "var(--dsw-alias-label-tertiary, #adb2b8)",
1422
- fontSize: "0.92em"
1423
- },
1508
+ /** #934:原先这里有一格 `version`(各家附加块的版本行字面)。版本行已按维护者裁定整条撤掉
1509
+ *(那两家面板内的渲染点 + 六家各自那份字面副本),这一格随之删除:没人取的槽位不留。 */
1424
1510
  /** `.ic-badge{font-size:11px;line-height:1;padding:4px 9px;border-radius:999px;white-space:nowrap;
1425
1511
  * display:inline-flex;align-items:center;gap:6px;border:1px solid transparent}`(11px ⇒ `0.88em`)。 */
1426
1512
  badge: {
@@ -1619,7 +1705,18 @@ window.__ModuleLoader__.load({
1619
1705
  kind: badge,
1620
1706
  dirtyCount
1621
1707
  }));
1622
- const fileLines = surface === null ? null : react.createElement("div", { style: S.fileWrap }, react.createElement("div", { style: S.info }, react.createElement("b", { style: S.fileLabel }, "配置文件"), surface.path), react.createElement("div", { style: S.info }, react.createElement("b", { style: S.fileLabel }, "数据目录"), headDataDir), surface.created ? react.createElement("div", { style: S.muted }, "(配置文件刚按默认值生成)") : null);
1708
+ /** #939:这一块的高度由**客户端常量**决定、不由回执时序决定——加载期就把两行连标签一起画出来,
1709
+ * 值位画骨架条(`.ic-sk`),回执到了**原地填值** ⇒ 回执零位移(原先加载期只画一行小灰字、
1710
+ * 回执到了才长出两行,整块下移 21px)。
1711
+ *
1712
+ * 判断式按 `state.kind`:**不许**照 `surface === null` 写——它同时覆盖失败态,照写会让失败屏长出两行假骨架。 */
1713
+ const loading = state.kind === "loading";
1714
+ const fileValue = (text) => text === null ? react.createElement("span", {
1715
+ style: S.skeleton,
1716
+ "data-ilife-skeleton": "value"
1717
+ }) : text;
1718
+ const fileRow = (label, text, tail) => react.createElement("div", { style: S.info }, react.createElement("b", { style: S.fileLabel }, label), fileValue(text), tail === void 0 ? null : tail);
1719
+ const fileLines = !loading && surface === null ? null : react.createElement("div", { style: S.fileWrap }, fileRow("配置文件", surface === null ? null : surface.path, surface !== null && surface.created ? react.createElement("span", { style: S.muted }, "(配置文件刚按默认值生成)") : null), fileRow("数据目录", surface === null ? null : headDataDir));
1623
1720
  const parts = {
1624
1721
  styles: S,
1625
1722
  reply: surface
@@ -1663,7 +1760,7 @@ window.__ModuleLoader__.load({
1663
1760
  const commonLast = lastIndexOf(common);
1664
1761
  const advancedLast = lastIndexOf(advanced);
1665
1762
  const dirty = ready && dirtyCount > 0;
1666
- return react.createElement("div", { style: S.card }, head, fileLines, ready ? null : react.createElement("div", { style: S.muted }, "配置读取中"), react.createElement("div", { style: S.rows }, common.map((item, index) => renderRow(item, index === commonLast))), advanced.length === 0 ? null : react.createElement("details", { style: S.advanced }, react.createElement("summary", { style: S.summary }, react.createElement("span", { style: S.groupMark }, "›"), ADVANCED_GROUP_TITLE, react.createElement("span", { style: S.groupNote }, ADVANCED_GROUP_NOTE)), react.createElement("div", { style: S.groupBody }, advanced.map((item, index) => renderRow(item, index === advancedLast)))), extra, react.createElement("div", { style: S.bar }, react.createElement("button", {
1763
+ return react.createElement("div", { style: S.card }, head, fileLines, react.createElement("div", { style: S.rows }, common.map((item, index) => renderRow(item, index === commonLast))), advanced.length === 0 ? null : react.createElement("details", { style: S.advanced }, react.createElement("summary", { style: S.summary }, react.createElement("span", { style: S.groupMark }, "›"), ADVANCED_GROUP_TITLE), react.createElement("div", { style: S.groupBody }, advanced.map((item, index) => renderRow(item, index === advancedLast)))), extra, react.createElement("div", { style: S.bar }, react.createElement("button", {
1667
1764
  style: dirty ? S.btnPrimary : S.btn,
1668
1765
  type: "button",
1669
1766
  disabled: frozen || !dirty,
@@ -1678,7 +1775,7 @@ window.__ModuleLoader__.load({
1678
1775
  type: "button",
1679
1776
  disabled: frozen,
1680
1777
  onClick: props.onRetry
1681
- }, "重新读取"), dirty ? react.createElement("div", { style: S.saveMsg }, `浏览改动后请点保存(${dirtyCount} 项未保存),保存后跟随项自动更新`) : ready ? react.createElement("div", { style: S.barNote }, "没有未保存的改动") : null), props.picking ? react.createElement("div", { style: S.muted }, "已唤起系统文件夹对话框:选中后自动填上,取消则不动。") : null, props.browseRow !== null ? react.createElement(DirectoryBrowserFromRow, {
1778
+ }, "重新读取"), dirty ? react.createElement("div", { style: S.saveMsg }, `浏览改动后请点保存(${dirtyCount} 项未保存),保存后跟随项自动更新`) : ready ? react.createElement("div", { style: S.barNote }, "没有未保存的改动") : react.createElement("div", { style: S.barNote }, "配置读取中")), props.picking ? react.createElement("div", { style: S.muted }, "已唤起系统文件夹对话框:选中后自动填上,取消则不动。") : null, props.browseRow !== null ? react.createElement(DirectoryBrowserFromRow, {
1682
1779
  open: true,
1683
1780
  row: props.browseRow,
1684
1781
  labels: BROWSER_LABELS
@@ -1687,6 +1784,39 @@ window.__ModuleLoader__.load({
1687
1784
  role: "alert"
1688
1785
  }, props.writeError) : null, props.error !== null ? react.createElement("div", { style: S.error }, props.error) : null, props.notice !== null ? react.createElement("div", { style: S.okText }, props.notice) : null);
1689
1786
  }
1787
+ /** 状态点的底色:三档状态色 + 默认灰(照真源 `.is-ok/.is-warn/.is-bad` 与 `.ic-dot` 的默认档)。 */
1788
+ const STATUS_DOT_COLOR = {
1789
+ ok: "var(--dsw-alias-state-success-primary, #4ec9a0)",
1790
+ warn: "var(--dsw-alias-state-warn-primary, #e0a33e)",
1791
+ bad: "var(--dsw-alias-state-error-primary, #e0685f)",
1792
+ pending: "var(--dsw-alias-label-tertiary, #adb2b8)"
1793
+ };
1794
+ function StatusBlock(props) {
1795
+ const actions = props.actions ?? [];
1796
+ return react.createElement("div", {
1797
+ style: S.statusBox,
1798
+ "data-ilife-status": "block"
1799
+ }, react.createElement("div", { style: S.statusRow }, react.createElement("span", { style: {
1800
+ ...S.statusDot,
1801
+ background: STATUS_DOT_COLOR[props.tone]
1802
+ } }), react.createElement("span", { style: S.statusName }, props.name), react.createElement("span", { style: S.statusText }, props.text), ...actions.map((action, index) => react.createElement("button", {
1803
+ key: action.text,
1804
+ style: index === 0 ? {
1805
+ ...S.btnPick,
1806
+ marginLeft: "auto"
1807
+ } : S.btnPick,
1808
+ type: "button",
1809
+ onClick: action.onPress
1810
+ }, action.text))), react.createElement("div", { style: S.statusFind }, props.path === null ? react.createElement("span", {
1811
+ style: S.skeleton,
1812
+ "data-ilife-skeleton": "statusPath"
1813
+ }) : react.createElement("span", { style: S.statusPath }, props.path), props.version === void 0 || props.version === null || props.version === "" ? null : react.createElement("span", { style: S.statusVersion }, props.version)), props.link === void 0 ? null : react.createElement("a", {
1814
+ style: S.statusUrl,
1815
+ href: props.link.href,
1816
+ target: "_blank",
1817
+ rel: "noreferrer"
1818
+ }, props.link.text));
1819
+ }
1690
1820
  //#endregion
1691
1821
  //#region ../plugin-manager/dist/directory-browser-roots.js
1692
1822
  /** 「本机根清单」的取数接线(客户端半):把一通电话变成图上那一行可跳转的根。
@@ -2238,13 +2368,14 @@ window.__ModuleLoader__.load({
2238
2368
  function followKeysOf(dirtyKeys) {
2239
2369
  return dirtyKeys.includes("db.dir") ? [...DB_FOLLOWERS] : [];
2240
2370
  }
2241
- /** 「飞书 CLI」状态行(#764,定稿 #761):不是配置项——三档读数由技能侧体检出,面板只显示;
2242
- * 三档都有「复制 prompt」按钮与官网那一行(逐字、可点击)。
2371
+ /** 「飞书 CLI」状态行(#764 定稿 #761;**#936 起照真源 `.ic-status` 画**):不是配置项——
2372
+ * 三档读数由技能侧体检出,面板只显示;**形状由共用件的 `StatusBlock` 给**(两家同形)。
2373
+ * 两枚按钮的字面照真源:左「复制安装指引」、右「重新检测」。骨架期画「检测中」+ 路径位骨架条、
2374
+ * 两枚按钮照画 ⇒ 与就绪态同高(真源 `planRows()` 的口径:骨架期就定行高,填充时不跳)。
2243
2375
  *
2244
2376
  * 为什么单起一个组件:这通体检电话是本家自己的(共用面板不认识 `config.check` 的回执),
2245
2377
  * 组件自己持读数与「复制回执」两点状态,面板只管把它画进插槽。 */
2246
2378
  function LarkLine(props) {
2247
- const S = props.styles;
2248
2379
  const [lark, setLark] = react.useState({ kind: "loading" });
2249
2380
  const [copied, setCopied] = react.useState("idle");
2250
2381
  const loadHealth = react.useCallback(async () => {
@@ -2263,7 +2394,8 @@ window.__ModuleLoader__.load({
2263
2394
  message: "体检回执里没有飞书 CLI 那一项"
2264
2395
  } : {
2265
2396
  kind: "ready",
2266
- item
2397
+ item,
2398
+ reading: r.report.lark ?? null
2267
2399
  });
2268
2400
  }, [props.getCall]);
2269
2401
  react.useEffect(() => {
@@ -2274,27 +2406,58 @@ window.__ModuleLoader__.load({
2274
2406
  const ok = await copyText(LARK_PROMPT_V5, { clipboard: clipboardOf() ?? void 0 });
2275
2407
  setCopied(ok ? "done" : "failed");
2276
2408
  };
2277
- if (lark.kind === "loading") return react.createElement("div", { style: S.rows }, react.createElement("div", { style: S.label }, "飞书 CLI"), react.createElement("div", { style: S.muted }, "飞书 CLI 检测中"));
2278
- if (lark.kind === "failed") return react.createElement("div", { style: S.rows }, react.createElement("div", { style: S.label }, "飞书 CLI"), react.createElement("div", { style: S.error }, lark.message), react.createElement("div", { style: S.bar }, react.createElement("button", {
2279
- style: S.btn,
2280
- type: "button",
2281
- onClick: () => void loadHealth()
2282
- }, "重新检测")));
2409
+ if (lark.kind === "loading") return react.createElement(StatusBlock, {
2410
+ name: "飞书 CLI",
2411
+ tone: "pending",
2412
+ text: "检测中",
2413
+ path: null,
2414
+ version: null,
2415
+ actions: [{
2416
+ text: "复制安装指引",
2417
+ onPress: () => void onCopyPrompt()
2418
+ }, {
2419
+ text: "重新检测",
2420
+ onPress: () => void loadHealth()
2421
+ }],
2422
+ link: {
2423
+ text: LARK_OFFICIAL_LINE,
2424
+ href: LARK_OFFICIAL_URL
2425
+ }
2426
+ });
2427
+ if (lark.kind === "failed") return react.createElement(StatusBlock, {
2428
+ name: "飞书 CLI",
2429
+ tone: "bad",
2430
+ text: lark.message,
2431
+ path: "",
2432
+ actions: [{
2433
+ text: "重新检测",
2434
+ onPress: () => void loadHealth()
2435
+ }],
2436
+ link: {
2437
+ text: LARK_OFFICIAL_LINE,
2438
+ href: LARK_OFFICIAL_URL
2439
+ }
2440
+ });
2283
2441
  const item = lark.item;
2284
- const tone = item.status === "green" ? S.okText : item.status === "red" ? S.error : S.muted;
2285
- return react.createElement("div", { style: S.rows }, react.createElement("div", { style: S.label }, "飞书 CLI"), react.createElement("div", { style: tone }, item.message), item.action === "" ? null : react.createElement("div", { style: S.hint }, item.action), react.createElement("div", { style: S.bar }, react.createElement("button", {
2286
- style: S.btn,
2287
- type: "button",
2288
- onClick: () => void onCopyPrompt()
2289
- }, "复制 prompt"), react.createElement("button", {
2290
- style: S.btn,
2291
- type: "button",
2292
- onClick: () => void loadHealth()
2293
- }, "重新检测")), copied === "done" ? react.createElement("div", { style: S.okText }, "已复制安装指引") : copied === "failed" ? react.createElement("div", { style: S.error }, "复制失败:剪贴板不可用,请手动复制对话框里的安装指引") : null, react.createElement("div", { style: S.info }, react.createElement("a", {
2294
- href: LARK_OFFICIAL_URL,
2295
- target: "_blank",
2296
- rel: "noreferrer"
2297
- }, LARK_OFFICIAL_LINE)));
2442
+ const reading = lark.reading;
2443
+ return react.createElement("div", null, react.createElement(StatusBlock, {
2444
+ name: "飞书 CLI",
2445
+ tone: item.status === "green" ? "ok" : item.status === "red" ? "bad" : "warn",
2446
+ text: item.status === "green" ? "已登录,日历可读" : item.status === "red" ? "没找到飞书 CLI" : "找到了,但还没登录/日历读不到",
2447
+ path: reading?.cliPath ?? "",
2448
+ version: reading?.version ?? null,
2449
+ actions: [{
2450
+ text: "复制安装指引",
2451
+ onPress: () => void onCopyPrompt()
2452
+ }, {
2453
+ text: "重新检测",
2454
+ onPress: () => void loadHealth()
2455
+ }],
2456
+ link: {
2457
+ text: LARK_OFFICIAL_LINE,
2458
+ href: LARK_OFFICIAL_URL
2459
+ }
2460
+ }), copied === "done" ? react.createElement("div", { style: props.styles.okText }, "已复制安装指引") : copied === "failed" ? react.createElement("div", { style: props.styles.error }, "复制失败:剪贴板不可用,请手动复制对话框里的安装指引") : null);
2298
2461
  }
2299
2462
  function apply(ctx) {
2300
2463
  const getCall = () => ctx.connection?.rpc?.call ?? null;