dsh-life-pack 0.2.5 → 0.2.6
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 +148 -53
- package/dist/client.js.map +1 -1
- package/dist/health-view.d.ts.map +1 -1
- package/dist/health-view.js +81 -16
- package/dist/health-view.js.map +1 -1
- package/dist/nav.d.ts +1 -1
- package/dist/nav.js +1 -1
- package/dist/update-contract.d.ts +8 -1
- package/dist/update-contract.d.ts.map +1 -1
- package/dist/update-contract.js +8 -1
- package/dist/update-contract.js.map +1 -1
- package/dist/update-env.d.ts +16 -0
- package/dist/update-env.d.ts.map +1 -1
- package/dist/update-env.js +70 -0
- package/dist/update-env.js.map +1 -1
- package/dist/update-host.d.ts.map +1 -1
- package/dist/update-host.js +4 -1
- package/dist/update-host.js.map +1 -1
- package/dist/update-view.d.ts +12 -0
- package/dist/update-view.d.ts.map +1 -1
- package/dist/update-view.js +10 -0
- package/dist/update-view.js.map +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -132,6 +132,13 @@ window.__ModuleLoader__.load({
|
|
|
132
132
|
];
|
|
133
133
|
//#endregion
|
|
134
134
|
//#region src/update-contract.ts
|
|
135
|
+
/** 爱生活页签槽名(总管声明 `children`、各单品技能设置页注册进来;单段名,避开官方 `settings.*` 前缀)。
|
|
136
|
+
*
|
|
137
|
+
* 为什么住这里:这个名字**两侧都要用**——面板侧 `client.ts` 拿它注册/投影槽,
|
|
138
|
+
* 宿主侧(`update-env.ts` 的 `readPanelRegistered`)拿它判「已装产物里到底有没有注册代码」。
|
|
139
|
+
* 一处定义、两边引用(结构纪律「概念唯一」):名字改了只有这一行要动。
|
|
140
|
+
* 宿主判据为什么要读这个字面量、以及它的边界,见 `readPanelRegistered` 的头注。 */
|
|
141
|
+
const CONFIG_TAB_SLOT = "ilife.config-tab";
|
|
135
142
|
/** 载体:宿主注册 `connection.fetch.register` 的路径 / 面板 `connection.rpc.call` 的两段参数。 */
|
|
136
143
|
const MANAGER_RPC = {
|
|
137
144
|
/** 载体基段(`connection.rpc.call` 的**第一段**参数)。传错第一段就是 404:真机上踩过一次。 */
|
|
@@ -147,7 +154,7 @@ window.__ModuleLoader__.load({
|
|
|
147
154
|
const MANAGER_ACTIONS = {
|
|
148
155
|
/** 装上缺席的目标包:入参 `{packageName, version}`,回包 `{packageName, version}`。 */
|
|
149
156
|
install: "ilife-manager.install",
|
|
150
|
-
/** 七个更新目标的表:入参 `{}`,回包 `{targets: [{key, title, packageName, phones, runningVersion, installedVersion, skill}]}`。
|
|
157
|
+
/** 七个更新目标的表:入参 `{}`,回包 `{targets: [{key, title, packageName, phones, runningVersion, installedVersion, panelRegistered, skill}]}`。
|
|
151
158
|
*
|
|
152
159
|
* 电话名为什么由宿主转交而不是面板侧写死:更新包的三个电话名只有它自己知道
|
|
153
160
|
* (`update.phoneNames`,`host.ts:335`);面板侧既不能 import 更新包(浏览器产物纯度门)
|
|
@@ -308,6 +315,13 @@ window.__ModuleLoader__.load({
|
|
|
308
315
|
function isAbsent(target) {
|
|
309
316
|
return target.runningVersion === null && target.installedVersion === null;
|
|
310
317
|
}
|
|
318
|
+
/** 一家页签此刻的状态:账本里已注册 → `connected`(面板显示它自己的设置页),否则按宿主装机读数分三态。 */
|
|
319
|
+
function slotStateOf(target, inLedger) {
|
|
320
|
+
if (inLedger) return "connected";
|
|
321
|
+
if (target === null || isAbsent(target)) return "absent";
|
|
322
|
+
if (target.panelRegistered === false) return "unregistered-product";
|
|
323
|
+
return "not-connected";
|
|
324
|
+
}
|
|
311
325
|
/** 把快照翻成一行结论:还没查 / 已是最新 / 有新版 / 装不了(附人话原因)。 */
|
|
312
326
|
function verdictOf(target, snapshot) {
|
|
313
327
|
const absent = isAbsent(target);
|
|
@@ -564,20 +578,23 @@ window.__ModuleLoader__.load({
|
|
|
564
578
|
const [loadError, setLoadError] = react.useState(null);
|
|
565
579
|
const [checking, setChecking] = react.useState(false);
|
|
566
580
|
const [open, setOpen] = react.useState(false);
|
|
567
|
-
react.
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
};
|
|
581
|
+
const alive = react.useRef(true);
|
|
582
|
+
react.useEffect(() => () => {
|
|
583
|
+
alive.current = false;
|
|
584
|
+
}, []);
|
|
585
|
+
/** 重取七个目标的表(装机读数变了就重取:缺席卡的态是拿这张表算的,缓存住它会继续说旧话)。 */
|
|
586
|
+
const reload = react.useCallback(async () => {
|
|
587
|
+
const loaded = await loadTargets(getCall());
|
|
588
|
+
if (!alive.current) return;
|
|
589
|
+
if (loaded.ok) {
|
|
590
|
+
setTargets(loaded.value.targets);
|
|
591
|
+
setPollMs(loaded.value.pollMs);
|
|
592
|
+
setLoadError(null);
|
|
593
|
+
} else setLoadError(loaded.message);
|
|
580
594
|
}, [getCall]);
|
|
595
|
+
react.useEffect(() => {
|
|
596
|
+
reload();
|
|
597
|
+
}, [reload]);
|
|
581
598
|
const patch = react.useCallback((key, next) => {
|
|
582
599
|
setRows((previous) => ({
|
|
583
600
|
...previous,
|
|
@@ -658,6 +675,7 @@ window.__ModuleLoader__.load({
|
|
|
658
675
|
outcome: null,
|
|
659
676
|
failure: refreshed
|
|
660
677
|
});
|
|
678
|
+
await reload();
|
|
661
679
|
return;
|
|
662
680
|
}
|
|
663
681
|
patch(target.key, {
|
|
@@ -673,6 +691,7 @@ window.__ModuleLoader__.load({
|
|
|
673
691
|
getCall,
|
|
674
692
|
patch,
|
|
675
693
|
pollMs,
|
|
694
|
+
reload,
|
|
676
695
|
rows
|
|
677
696
|
])
|
|
678
697
|
};
|
|
@@ -771,14 +790,16 @@ window.__ModuleLoader__.load({
|
|
|
771
790
|
"aria-label": "关闭"
|
|
772
791
|
}, "×")), body, react.createElement("div", { style: PANEL_STYLE.dialogNote }, "装与更新都在宿主后台跑:关掉这块不影响正在进行的安装,再点「检查更新」可以看到最新状态。"))) : null);
|
|
773
792
|
}
|
|
774
|
-
/**
|
|
793
|
+
/** 缺席卡:**按两处独立事实分三态**,每态只给能改变状态的动作。
|
|
775
794
|
*
|
|
776
|
-
* -
|
|
777
|
-
* -
|
|
778
|
-
*
|
|
779
|
-
*
|
|
795
|
+
* - `absent`(磁盘上没有这个包)→「未安装」+「装上」按钮(本票原有的能力);
|
|
796
|
+
* - `unregistered-product`(装着,但产物里没有页签槽注册代码)→ 说实情、**不给按钮**:
|
|
797
|
+
* 重装改不了产物里有没有注册代码(真机实测:作息/居家/大厨/记账 的已发布 0.2.0
|
|
798
|
+
* 产物里根本没有注册代码,见票 #723);给可复制命令只是参考;
|
|
799
|
+
* - `not-connected`(装着、产物也有注册代码,设置页却没送到浏览器)→ 重启宿主;仍不行看日志;
|
|
800
|
+
* - `connected` 不归本卡管:那时面板显示的是那家自己的设置页。
|
|
780
801
|
*
|
|
781
|
-
* 原实现只看页签槽 ledger
|
|
802
|
+
* 原实现只看页签槽 ledger 就断言「未安装」——那对后两种情形是说假话,且点「装上」
|
|
782
803
|
* 会走进更新包的流程(它已经装着 ⇒ 没有新版 ⇒ 没有凭证)并报出误导的「查新版失败」。
|
|
783
804
|
*/
|
|
784
805
|
function AbsentCard(props) {
|
|
@@ -787,10 +808,20 @@ window.__ModuleLoader__.load({
|
|
|
787
808
|
const busy = row?.phase === "installing";
|
|
788
809
|
const manual = (target ? manualForDisplay(target, row?.failure?.manual ?? row?.outcome?.manual ?? null) : null) ?? props.fallbackCommand;
|
|
789
810
|
const installed = target ? target.installedVersion ?? target.runningVersion : null;
|
|
811
|
+
const state = slotStateOf(target, props.inLedger);
|
|
790
812
|
let reason = row?.failure?.message ?? null;
|
|
791
813
|
if (target && reason === null && row?.outcome && row.outcome.snapshot.blockedReason !== null) reason = verdictOf(target, row.outcome.snapshot).text;
|
|
792
|
-
|
|
793
|
-
|
|
814
|
+
let headline;
|
|
815
|
+
switch (state) {
|
|
816
|
+
case "absent":
|
|
817
|
+
headline = target ? "未安装[" + target.packageName + "],装上后这个页签就能用了。" : "这个页签对应的插件还没装。";
|
|
818
|
+
break;
|
|
819
|
+
case "unregistered-product":
|
|
820
|
+
headline = target.packageName + " " + String(installed) + " 装着,但它这一版的产物里没有爱生活页签的注册代码:得等它发一个带注册代码的新版才对得上。重启与重装都不会变(重装只是把同一版再装一次)。";
|
|
821
|
+
break;
|
|
822
|
+
default: headline = target.packageName + " " + String(installed) + " 装着、产物里也有注册代码,但它的设置页没送到浏览器:重启宿主后再看这个页签;仍然这样就去宿主日志里找它的报错。";
|
|
823
|
+
}
|
|
824
|
+
return react.createElement("div", { style: PANEL_STYLE.reco }, react.createElement("div", null, headline), state === "absent" ? react.createElement("button", {
|
|
794
825
|
type: "button",
|
|
795
826
|
style: busy ? {
|
|
796
827
|
...PANEL_STYLE.btn,
|
|
@@ -801,7 +832,9 @@ window.__ModuleLoader__.load({
|
|
|
801
832
|
marginTop: 8
|
|
802
833
|
},
|
|
803
834
|
disabled: busy,
|
|
804
|
-
onClick: () =>
|
|
835
|
+
onClick: () => {
|
|
836
|
+
if (target) props.face.act(target);
|
|
837
|
+
}
|
|
805
838
|
}, busy ? "正在装,请稍候…" : "装上") : null, reason ? react.createElement("div", { style: PANEL_STYLE.reason }, reason) : null, react.createElement("code", { style: PANEL_STYLE.cmd }, manual));
|
|
806
839
|
}
|
|
807
840
|
//#endregion
|
|
@@ -990,8 +1023,10 @@ window.__ModuleLoader__.load({
|
|
|
990
1023
|
green: "var(--dsw-alias-state-success-primary, #4ec9a0)"
|
|
991
1024
|
};
|
|
992
1025
|
/** 整行底色的浅一档:饱和降一档,免得红黄行「刺眼」压过正文(评审第二轮的扣分点)。 */
|
|
1026
|
+
/** 红黄两档整行上底的底色。红灯要**明显重于**黄灯:复评实测原先两个底色亮度几乎一样
|
|
1027
|
+
* (红 `#FBF3F3` 对黄 `#FCF3E5`,只差蓝通道),最严重那一档反而最淡——红色提到 0.14。 */
|
|
993
1028
|
const STATUS_TINT = {
|
|
994
|
-
red: "rgba(192, 57, 43, 0.
|
|
1029
|
+
red: "rgba(192, 57, 43, 0.14)",
|
|
995
1030
|
yellow: "rgba(224, 138, 0, 0.10)",
|
|
996
1031
|
green: "transparent"
|
|
997
1032
|
};
|
|
@@ -1128,11 +1163,6 @@ window.__ModuleLoader__.load({
|
|
|
1128
1163
|
}
|
|
1129
1164
|
return prefixes.sort((a, b) => b.length - a.length);
|
|
1130
1165
|
}
|
|
1131
|
-
/** 那一行「配置文件 … · 数据目录 …」+ 各条报文里的长路径,都缩成「公共前缀 + 短尾巴」。 */
|
|
1132
|
-
function shorten(path, prefixes) {
|
|
1133
|
-
const hit = prefixes.find((prefix) => path.startsWith(prefix + "/"));
|
|
1134
|
-
return hit === void 0 ? path : "…/" + path.slice(hit.length + 1);
|
|
1135
|
-
}
|
|
1136
1166
|
/** 一家里所有会印出来的路径。 */
|
|
1137
1167
|
function pathsOf(report) {
|
|
1138
1168
|
const out = [report.configPath, report.dataDir];
|
|
@@ -1157,11 +1187,12 @@ window.__ModuleLoader__.load({
|
|
|
1157
1187
|
function lightsOf(tabs, reports) {
|
|
1158
1188
|
return tabs.map((tab) => {
|
|
1159
1189
|
const report = reports[tab.id];
|
|
1190
|
+
const items = report?.items ?? [];
|
|
1160
1191
|
return {
|
|
1161
1192
|
id: tab.id,
|
|
1162
1193
|
title: tab.title,
|
|
1163
|
-
status: report ? worstStatus(
|
|
1164
|
-
counts: countByStatus(
|
|
1194
|
+
status: report ? worstStatus(items) : null,
|
|
1195
|
+
counts: countByStatus(items)
|
|
1165
1196
|
};
|
|
1166
1197
|
});
|
|
1167
1198
|
}
|
|
@@ -1173,6 +1204,42 @@ window.__ModuleLoader__.load({
|
|
|
1173
1204
|
if (parts.length === 0) return "绿";
|
|
1174
1205
|
return parts.join(" · ");
|
|
1175
1206
|
}
|
|
1207
|
+
/** 「红 2 · 黄 3」那一截**按档上色**:每一档用它自己的字色、分隔符走淡色。
|
|
1208
|
+
* 为什么必须拆开:原先整截塞进一个 span、染「最严重那一档」的颜色,六家都红时「黄 3」就跟着印成红字——
|
|
1209
|
+
* 本页自己说「黄=还没配」,文字层却把它涂成红(出图复评五份里三份独立指到,取色同为 `#c03828`)。 */
|
|
1210
|
+
function countSegments(light) {
|
|
1211
|
+
if (light.status === null) return [react.createElement("span", {
|
|
1212
|
+
key: "dash",
|
|
1213
|
+
style: {
|
|
1214
|
+
color: INK_DIM,
|
|
1215
|
+
fontWeight: 700
|
|
1216
|
+
}
|
|
1217
|
+
}, "—")];
|
|
1218
|
+
const parts = [];
|
|
1219
|
+
for (const status of ["red", "yellow"]) {
|
|
1220
|
+
const count = light.counts[status];
|
|
1221
|
+
if (count === 0) continue;
|
|
1222
|
+
if (parts.length > 0) parts.push(react.createElement("span", {
|
|
1223
|
+
key: status + "-sep",
|
|
1224
|
+
style: { color: INK_DIM }
|
|
1225
|
+
}, " · "));
|
|
1226
|
+
parts.push(react.createElement("span", {
|
|
1227
|
+
key: status,
|
|
1228
|
+
style: {
|
|
1229
|
+
color: STATUS_TEXT[status],
|
|
1230
|
+
fontWeight: 700
|
|
1231
|
+
}
|
|
1232
|
+
}, STATUS_LABEL[status] + " " + String(count)));
|
|
1233
|
+
}
|
|
1234
|
+
if (parts.length === 0) return [react.createElement("span", {
|
|
1235
|
+
key: "green",
|
|
1236
|
+
style: {
|
|
1237
|
+
color: INK_DIM,
|
|
1238
|
+
fontWeight: 700
|
|
1239
|
+
}
|
|
1240
|
+
}, "绿")];
|
|
1241
|
+
return parts;
|
|
1242
|
+
}
|
|
1176
1243
|
/** 顶部那行总览:六家一盏灯 + 一个「体检一次」按钮。 */
|
|
1177
1244
|
function HealthOverview(props) {
|
|
1178
1245
|
return react.createElement("div", {
|
|
@@ -1217,10 +1284,33 @@ window.__ModuleLoader__.load({
|
|
|
1217
1284
|
} }), react.createElement("span", { style: {
|
|
1218
1285
|
color: INK,
|
|
1219
1286
|
fontWeight: 650
|
|
1220
|
-
} }, light.title), react.createElement("
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1287
|
+
} }, light.title), ...countSegments(light)))), react.createElement("div", { style: HEALTH_STYLE.meta }, props.error !== null ? props.error : [
|
|
1288
|
+
react.createElement("span", {
|
|
1289
|
+
key: "r",
|
|
1290
|
+
style: {
|
|
1291
|
+
color: STATUS_TEXT.red,
|
|
1292
|
+
fontWeight: 700
|
|
1293
|
+
}
|
|
1294
|
+
}, "红"),
|
|
1295
|
+
react.createElement("span", { key: "r2" }, "=坏了 · "),
|
|
1296
|
+
react.createElement("span", {
|
|
1297
|
+
key: "y",
|
|
1298
|
+
style: {
|
|
1299
|
+
color: STATUS_TEXT.yellow,
|
|
1300
|
+
fontWeight: 700
|
|
1301
|
+
}
|
|
1302
|
+
}, "黄"),
|
|
1303
|
+
react.createElement("span", { key: "y2" }, "=还没配 · "),
|
|
1304
|
+
react.createElement("span", {
|
|
1305
|
+
key: "g",
|
|
1306
|
+
style: {
|
|
1307
|
+
color: STATUS_TEXT.green,
|
|
1308
|
+
fontWeight: 700
|
|
1309
|
+
}
|
|
1310
|
+
}, "绿"),
|
|
1311
|
+
react.createElement("span", { key: "g2" }, "=正常 | 只看不改:不建目录、不改配置、不自动重置"),
|
|
1312
|
+
react.createElement("span", { key: "tab" }, " · 上面那排圆点是体检灯,点一下跳到那家配置页;下面那排圆点是页签(实心=装上了)")
|
|
1313
|
+
]));
|
|
1224
1314
|
}
|
|
1225
1315
|
/** 正正常常的那些:绿条只留「名字」,一句话与「去哪修」都不印(票面验收第一条:正常的收成一行)。 */
|
|
1226
1316
|
function isAttentionItem(item) {
|
|
@@ -1237,10 +1327,11 @@ window.__ModuleLoader__.load({
|
|
|
1237
1327
|
}, react.createElement("div", { style: HEALTH_STYLE.headRow }, react.createElement("div", { style: HEALTH_STYLE.head }, props.title + " · 体检"), report ? react.createElement("div", { style: {
|
|
1238
1328
|
color: INK_DIM,
|
|
1239
1329
|
fontSize: 12
|
|
1240
|
-
} }, countsText(countByStatus(report.items))) : null), props.phase === "idle" ? react.createElement("div", { style: HEALTH_STYLE.meta }, "还没体检:点上面那个「体检一次」。") : null, props.phase === "running" ? react.createElement("div", { style: HEALTH_STYLE.meta }, "正在体检…") : null, props.error !== null ? react.createElement("div", { style: HEALTH_STYLE.error }, props.error) : null, report ? react.createElement("div", null, react.createElement("div", {
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1330
|
+
} }, countsText(countByStatus(report.items))) : null), props.phase === "idle" ? react.createElement("div", { style: HEALTH_STYLE.meta }, "还没体检:点上面那个「体检一次」。") : null, props.phase === "running" ? react.createElement("div", { style: HEALTH_STYLE.meta }, "正在体检…") : null, props.error !== null ? react.createElement("div", { style: HEALTH_STYLE.error }, props.error) : null, report ? react.createElement("div", null, report.dataDir !== "" ? react.createElement("div", { style: {
|
|
1331
|
+
color: INK_DIM,
|
|
1332
|
+
fontSize: 11.5,
|
|
1333
|
+
marginTop: 2
|
|
1334
|
+
} }, "落点根目录:" + report.dataDir + (report.configPath !== "" ? "(配置文件 " + report.configPath + ")" : "")) : null, report.items.filter(isAttentionItem).map((item) => react.createElement("div", {
|
|
1244
1335
|
key: item.id,
|
|
1245
1336
|
"data-ilife-health": "item",
|
|
1246
1337
|
"data-status": item.status,
|
|
@@ -1267,18 +1358,12 @@ window.__ModuleLoader__.load({
|
|
|
1267
1358
|
},
|
|
1268
1359
|
"aria-hidden": "true"
|
|
1269
1360
|
}, STATUS_MARK[item.status]), react.createElement("span", { style: {
|
|
1270
|
-
width: 8,
|
|
1271
|
-
height: 8,
|
|
1272
|
-
borderRadius: "50%",
|
|
1273
|
-
display: "inline-block",
|
|
1274
|
-
background: STATUS_COLOR[item.status]
|
|
1275
|
-
} }), react.createElement("span", { style: {
|
|
1276
1361
|
fontWeight: 650,
|
|
1277
1362
|
color: INK
|
|
1278
1363
|
} }, item.title), react.createElement("span", { style: {
|
|
1279
1364
|
color: STATUS_TEXT[item.status],
|
|
1280
1365
|
fontWeight: 700
|
|
1281
|
-
} }, STATUS_LABEL[item.status]), item.source ? react.createElement("span", { style: { color: INK_DIM } }, "· 来自" + item.source) : null), react.createElement("div", {
|
|
1366
|
+
} }, STATUS_LABEL[item.status]), item.source && item.source !== "默认值" ? react.createElement("span", { style: { color: INK_DIM } }, "· 来自" + item.source) : null), react.createElement("div", {
|
|
1282
1367
|
style: { color: INK },
|
|
1283
1368
|
title: item.message
|
|
1284
1369
|
}, shortenPathsIn(item.message, prefixes)), item.action.length > 0 ? react.createElement("div", { style: { color: INK_DIM } }, "去哪修:" + actionText(item.action)) : null)), report.items.some((item) => !isAttentionItem(item)) ? react.createElement("div", {
|
|
@@ -1289,16 +1374,27 @@ window.__ModuleLoader__.load({
|
|
|
1289
1374
|
alignItems: "center",
|
|
1290
1375
|
gap: "2px 10px",
|
|
1291
1376
|
marginTop: 8,
|
|
1292
|
-
|
|
1293
|
-
|
|
1377
|
+
padding: "6px 8px",
|
|
1378
|
+
borderLeft: "3px solid " + STATUS_COLOR.green,
|
|
1379
|
+
borderRadius: 6,
|
|
1294
1380
|
fontSize: 12,
|
|
1295
1381
|
lineHeight: 1.6,
|
|
1296
1382
|
color: INK_DIM
|
|
1297
1383
|
}
|
|
1298
|
-
}, react.createElement("span", {
|
|
1384
|
+
}, react.createElement("span", {
|
|
1385
|
+
style: {
|
|
1386
|
+
width: 8,
|
|
1387
|
+
height: 8,
|
|
1388
|
+
borderRadius: "50%",
|
|
1389
|
+
display: "inline-block",
|
|
1390
|
+
background: STATUS_COLOR.green,
|
|
1391
|
+
flex: "0 0 auto"
|
|
1392
|
+
},
|
|
1393
|
+
"aria-hidden": "true"
|
|
1394
|
+
}), react.createElement("span", { style: {
|
|
1299
1395
|
fontWeight: 650,
|
|
1300
1396
|
color: INK
|
|
1301
|
-
} }, "正常 " + String(countByStatus(report.items).green) + " 条"), report.items.filter((item) => !isAttentionItem(item)).map((item) => react.createElement("span", {
|
|
1397
|
+
} }, "正常 " + String(countByStatus(report.items).green) + " 条"), react.createElement("span", { style: { color: INK_DIM } }, "(下列各项都正常工作)"), report.items.filter((item) => !isAttentionItem(item)).map((item) => react.createElement("span", {
|
|
1302
1398
|
key: item.id,
|
|
1303
1399
|
"data-ilife-health": "ok-item"
|
|
1304
1400
|
}, "· " + item.title))) : null) : null);
|
|
@@ -1324,8 +1420,6 @@ window.__ModuleLoader__.load({
|
|
|
1324
1420
|
* 文案与网址都取自 nav.ts 的两张静态表,本文件只画不算。
|
|
1325
1421
|
*/
|
|
1326
1422
|
const inject = ["slots", "connection"];
|
|
1327
|
-
/** 爱生活页签槽(总管声明的 children,技能设置页注册进来;单段名,避开官方 settings.* 前缀)。 */
|
|
1328
|
-
const CONFIG_TAB_SLOT = "ilife.config-tab";
|
|
1329
1423
|
/** 总管视觉(内联 style;颜色走 DSH 主题别名,深浅主题自适应,写死值只做回退;与技能面板同语言)。 */
|
|
1330
1424
|
const S = {
|
|
1331
1425
|
headRow: {
|
|
@@ -1559,7 +1653,7 @@ window.__ModuleLoader__.load({
|
|
|
1559
1653
|
setActiveId(next.plugin);
|
|
1560
1654
|
tabRefs.current[nextIndex]?.focus();
|
|
1561
1655
|
}
|
|
1562
|
-
return react.createElement("div", null, react.createElement("div", { style: S.headRow }, react.createElement("div", { style: S.head }, "爱生活"), react.createElement("div", { style: S.headActions }, react.createElement(CheckUpdateButton, { face }), react.createElement(PanelActions, null))), react.createElement("div", { style: S.meta }, react.createElement("div", null, "总开关 · 开关(缺省启用,只读)"), react.createElement("div", null, "总管 dsh-life-pack · 0.2.
|
|
1656
|
+
return react.createElement("div", null, react.createElement("div", { style: S.headRow }, react.createElement("div", { style: S.head }, "爱生活"), react.createElement("div", { style: S.headActions }, react.createElement(CheckUpdateButton, { face }), react.createElement(PanelActions, null))), react.createElement("div", { style: S.meta }, react.createElement("div", null, "总开关 · 开关(缺省启用,只读)"), react.createElement("div", null, "总管 dsh-life-pack · 0.2.6")), react.createElement(UpdateResults, { face }), react.createElement(HealthOverview, {
|
|
1563
1657
|
lights: lightsOf(rows.map((row) => ({
|
|
1564
1658
|
id: row.id,
|
|
1565
1659
|
title: labelForTab(row.id)
|
|
@@ -1612,6 +1706,7 @@ window.__ModuleLoader__.load({
|
|
|
1612
1706
|
})) : react.createElement(AbsentCard, {
|
|
1613
1707
|
target: targetForTab(tab),
|
|
1614
1708
|
fallbackCommand: recoFor(tab).installCmd,
|
|
1709
|
+
inLedger: present.has(tab.plugin),
|
|
1615
1710
|
face
|
|
1616
1711
|
}));
|
|
1617
1712
|
}), react.createElement(MorePluginsCard, null));
|