build: 内网环境下跳过 Windows node-pty 补丁构建并关闭 GitHub 发布
Some checks failed
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
Star History / update (push) Has been cancelled

调整 electron-builder 配置,Windows 平台仅打包 zip 格式,注释掉 NSIS 和 portable 目标;
注释掉 Windows Hello helper 资源配置以避免路径不存在导致的打包失败;
将发布配置设为 null 以关闭 GitHub 发布请求;
修改 afterPack 脚本,跳过 Windows 下 node-pty ConPTY 补丁的重建和复制,因内网无 MSVC 工具链无法完成该操作。
This commit is contained in:
2026-10-15 15:30:31 +08:00
parent 2561001dca
commit 336c3afd47
7 changed files with 152 additions and 139 deletions

View File

@@ -94,10 +94,12 @@ function _severityLabel(sev) { return _severityInfo(sev).label; }
/** 健康分数 → 等级文本 */
function _healthLevelText(score) {
if (score >= 85) return "[健康]";
if (score >= 70) return "[良好],存在少量隐患";
if (score >= 50) return "[一般],需重点处置风险";
return "[较差],存在严重故障,需优先处置";
if (score >= 90) return "[优秀]";
if (score >= 80) return "[健康]";
if (score >= 70) return "[良好]";
if (score >= 60) return "[一般]";
if (score >= 40) return "[较差]";
return "[严重]";
}
function _severityColor(sev) {
@@ -110,42 +112,90 @@ function _severityColor(sev) {
// ─── 健康评分算法 ────────────────────────────────────
/** 单次巡检快照的健康评分(满分 100,最低 0) */
function calcSnapshotHealthScore(snap, aiSummary) {
let offlineCount = snap.devices.filter(d => !d.ok).length;
let critical = 0, warning = 0, info = 0, low = 0;
const risks = []; // [{ severity, count }]
// ─── 健康评分算法(多维度加权) ─────────────────────
// 满分 100,四维度加权:
// Reachability 40% 设备可及性 —— 在线设备占比
// Coverage 25% 巡检覆盖率 —— 命令成功率(仅在线设备)
// Risk 25% 隐患评级 —— AI hidden_risks 加权,上限 20
// Efficiency 10% 执行效率 —— 超时/时长异常
//
// 设计思路:
// - 比例扣分而非线性叠加:设备越多,单台离线扣分越小
// - 离线设备不参与覆盖率计算(本来就连不上)
// - Risk 维度有上限,防止 AI 隐患把总分打崩
// - Efficiency 权重偏低,因耗时不直接反映健康度
// AI 汇总里的 hidden_risks 按 severity 计数
if (aiSummary?.hidden_risks) {
for (const r of aiSummary.hidden_risks) {
const sev = r.severity || "info";
if (sev === "critical") critical++;
else if (sev === "warning") warning++;
else if (sev === "info") info++;
else low++;
risks.push({ severity: sev });
}
function calcSnapshotHealthScore(snap, aiSummary) {
const devices = snap?.devices || [];
const total = devices.length;
if (total === 0) {
return { score: 0, levelText: _healthLevelText(0), breakdown: "无设备数据" };
}
const deduct = offlineCount * 8 + critical * 12 + warning * 6 + info * 3 + low * 1;
const score = Math.max(0, 100 - deduct);
return {
score,
levelText: _healthLevelText(score),
deduction: {
offline: { count: offlineCount, points: offlineCount * 8 },
critical: { count: critical, points: critical * 12 },
warning: { count: warning, points: warning * 6 },
info: { count: info, points: info * 3 },
low: { count: low, points: low * 1 },
},
};
// ── 维度 1: 设备可及性(满分 40)─────────────────
const online = devices.filter(d => d.ok).length;
const offline = total - online;
const reachabilityScore = Math.round(40 * (online / total));
// ── 维度 2: 巡检覆盖率(满分 25)─────────────────
let totalCmds = 0, okCmds = 0;
for (const d of devices) {
if (!d.ok) continue; // 离线跳过
const cmds = d.commands || [];
for (const c of cmds) {
totalCmds++;
// command not found / 未识别 是框架 fallback,不算失败
if (!c.ok && /command not found|未识别|not recognized/i.test(c.stderr || c.stdout || "")) continue;
if (c.ok) okCmds++;
}
}
const coverageRatio = totalCmds === 0 ? 1 : okCmds / totalCmds;
const coverageScore = Math.round(25 * coverageRatio);
// ── 维度 3: 隐患评级(满分 25,上限扣 20)───────
const risks = aiSummary?.hidden_risks || [];
let riskPenalty = 0, riskCritical = 0, riskWarning = 0, riskInfo = 0;
for (const r of risks) {
if (!r || !r.severity) continue;
const sev = r.severity.toLowerCase();
if (sev === "critical") { riskPenalty += 5; riskCritical++; }
else if (sev === "warning" || sev === "high") { riskPenalty += 3; riskWarning++; }
else { riskPenalty += 1; riskInfo++; }
}
riskPenalty = Math.min(riskPenalty, 20); // 最多扣到只剩 5 分
const riskScore = 25 - riskPenalty;
// ── 维度 4: 执行效率(满分 10)───────────────────
let efficiencyScore = 10;
const durationMs = snap?.duration_ms || 0;
const avgMsPerDevice = total > 0 ? durationMs / total : 0;
if (avgMsPerDevice > 15000) {
const penalty = Math.min(6, Math.floor((avgMsPerDevice - 15000) / 10000));
efficiencyScore = 10 - penalty;
}
const timeoutDevices = devices.filter(d =>
d.ok && (d.commands || []).some(c => !c.ok && /ETIMEDOUT|timeout/i.test(c.stderr || c.stdout || ""))
).length;
if (timeoutDevices > 0) {
efficiencyScore = Math.max(4, efficiencyScore - Math.min(3, timeoutDevices));
}
// ── 最终得分(四维度求和)───────────────────────
const score = Math.max(0, reachabilityScore + coverageScore + riskScore + efficiencyScore);
const breakdown = [
`设备可及性: ${reachabilityScore}/40(在线 ${online}/${total})`,
`巡检覆盖率: ${coverageScore}/25(命令成功率 ${(coverageRatio * 100).toFixed(1)}%)`,
`隐患评级: ${riskScore}/25(隐患 ${risks.length} 条: 严重 ${riskCritical}, 警告 ${riskWarning}, 提示 ${riskInfo})`,
`执行效率: ${efficiencyScore}/10(平均 ${(avgMsPerDevice / 1000).toFixed(1)}s/台${timeoutDevices > 0 ? `, ${timeoutDevices} 台超时` : ""})`,
].join("\n");
return { score, levelText: _healthLevelText(score), breakdown };
}
/** 日报告健康评分(基于每个快照的分数,取算术平均 + max/min) */
function calcDailyHealthScore(snapScores) {
if (!snapScores || snapScores.length === 0) {
return { score: 0, levelText: "[一般],无快照数据", max: 0, min: 0 };
return { score: 0, levelText: _healthLevelText(0), max: 0, min: 0 };
}
const sum = snapScores.reduce((a, b) => a + b, 0);
const score = Math.round(sum / snapScores.length);