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
巡检模块:巡检调度器改为轮询驱动,新增每日报告存储、告警规则独立 Store、设备 Store 解耦,_executeSnapshot 补齐 DEBUG 声明,巡检中心 与告警中心页增强。 拓扑大屏:MonitoringTopologyView 扩展分组/布局控制, useMonitoringData 重构数据流。 远程 HTTP:新增 electron/remoteHttpServer.cjs,preload/api.cjs 暴露 IPC,registerBridges 注册 netcatty:http:open 桥。 portable 绿色打包: - electron-builder.config.cjs 恢复原始白名单(61MB app.asar), 收集器自动追踪运行时依赖; - portableData.cjs 重写为 .portable 标记检测; - scripts/migratePortableLocalStorage.cjs 离线脚本把 Local Storage 的 http://localhost:5173 origin 批量迁移为 app://netcatty; - scripts/scanWorkspaceDeps.cjs 扫描 workspace 运行时依赖。
98 lines
2.1 KiB
JavaScript
98 lines
2.1 KiB
JavaScript
"use strict";
|
||
|
||
/**
|
||
* 巡检模块主进程存储适配器
|
||
*
|
||
* 使用 userData 目录下的 JSON 文件存储巡检相关数据(设备配置、告警规则、巡检结果等)。
|
||
* 提供与 localStorage 类似的 key-value 接口,方便注入到 store 模块。
|
||
*/
|
||
|
||
const fs = require("node:fs");
|
||
const path = require("node:path");
|
||
|
||
const STORAGE_FILENAME = "inspection-data.json";
|
||
let _storageCache = null;
|
||
let _filePath = null;
|
||
let _dirty = false;
|
||
let _saveTimer = null;
|
||
|
||
function init(userDataDir) {
|
||
_filePath = path.join(userDataDir, STORAGE_FILENAME);
|
||
_loadFromDisk();
|
||
}
|
||
|
||
function _loadFromDisk() {
|
||
if (!_filePath) {
|
||
_storageCache = {};
|
||
return;
|
||
}
|
||
try {
|
||
if (fs.existsSync(_filePath)) {
|
||
const raw = fs.readFileSync(_filePath, "utf-8");
|
||
_storageCache = JSON.parse(raw);
|
||
} else {
|
||
_storageCache = {};
|
||
}
|
||
} catch (e) {
|
||
console.error("[Inspection Storage] 加载失败:", e?.message);
|
||
_storageCache = {};
|
||
}
|
||
}
|
||
|
||
function _scheduleSave() {
|
||
if (_saveTimer) return;
|
||
_saveTimer = setTimeout(() => {
|
||
_saveTimer = null;
|
||
_flushToDisk();
|
||
}, 200);
|
||
}
|
||
|
||
function _flushToDisk() {
|
||
if (!_filePath || !_dirty) return;
|
||
try {
|
||
const dir = path.dirname(_filePath);
|
||
if (!fs.existsSync(dir)) {
|
||
fs.mkdirSync(dir, { recursive: true });
|
||
}
|
||
fs.writeFileSync(_filePath, JSON.stringify(_storageCache, null, 2), "utf-8");
|
||
_dirty = false;
|
||
} catch (e) {
|
||
console.error("[Inspection Storage] 保存失败:", e?.message);
|
||
}
|
||
}
|
||
|
||
function readStorage(key) {
|
||
if (!_storageCache) _loadFromDisk();
|
||
return _storageCache[key] ?? null;
|
||
}
|
||
|
||
function writeStorage(key, value) {
|
||
if (!_storageCache) _loadFromDisk();
|
||
if (value === null || value === undefined) {
|
||
delete _storageCache[key];
|
||
} else {
|
||
_storageCache[key] = value;
|
||
}
|
||
_dirty = true;
|
||
_scheduleSave();
|
||
}
|
||
|
||
function flushSync() {
|
||
_flushToDisk();
|
||
}
|
||
|
||
function resetCache() {
|
||
// 先确保内存中的修改已写到磁盘(200ms 异步保存可能还没触发)
|
||
_flushToDisk();
|
||
_storageCache = null;
|
||
_loadFromDisk();
|
||
}
|
||
|
||
module.exports = {
|
||
init,
|
||
readStorage,
|
||
writeStorage,
|
||
flushSync,
|
||
resetCache,
|
||
};
|