😐 因为之前不知道什么原因下载了 gemini 的 mac 版,发现这个 spark 除了在云端做奇怪的新闻总结之类的,也可以链接本地文件,然后我琢磨是否可以用它写代码?正好自己几个 vps 流量都快超了,其实每天都在心算是否能坚持到重制日。索性试试看吧。最后证明 spark 是写代码还不错,至少不花钱……
今天花了大约两三个小时,借助 Gemini 把我的 Komari 网络流量预测插件(NetForecast)彻底打磨完善并顺利完成了提交上架。
整个协作过程高效且顺畅:起初插件首次加载偏慢,我与 Gemini 一起分析瓶颈,不仅加入了带超时保护的并发机制,还实现了一套带有分步状态指示的流光加载进度条;针对原本当日柱状图空白的问题,通过比对昨日基准与网卡实时计数器,精准实现了当日截至当前时间点的实时流量呈现。随后,我们将账单重置日与到期时间逻辑完全对齐,并重写了更加直观、带有高保真效果图的 README 文档。
最后,在 Gemini 的协助下,我们建立了自动打包发布的 GitHub Actions 工作流,成功发布了 v26.10.08 正式版本,并严格按照规范向 Komari 官方插件市场提交了上架申请。从性能排查、细节修复到最终开源分发,几个小时内一气呵成完成了高质量闭环。
以上是 gemini 自吹自擂的总结,其实大差不差,只是我描述完需求它直接动手干完了,我让它生成一个 html 的 mockup 才发现交互设计的问题,在 mockup 上调试妥当了让它写代码的时候,又擅作主张的把 mockup 的数据给写进去了,害我浪费了 20 分钟排查 bug。
在 github 的上传和 action 的编写方面的确非常丝滑。
因为刚刚做完,实际效果其实我还不知道,要等几天才能看到数据。
昨天本来以为没事了,结果实际使用中还是发现不少可以优化的地方,于是不知不觉又改了好多。Spark 有意思的是,它其实也有 usage quota,但是只能在网页上查看,而 gemini 的 spark 中不显示 usage 也不显示 model,看起来一切都是 auto routing 的。这对大众用户来说还是不错的。对开发者来说还是不太习惯。以下是 gemini 总结的昨天的日志
Journal 1: 图表与时间轴架构推倒重构 —— 统一账单周期坐标系
- 覆盖版本:
v26.10.08.1v26.10.08.2 - 问题背景:
在实际部署观测中,我发现原有图表存在多项违背业务常理与视觉体验的硬伤:
- 未来预测区间绘制了实心柱:未来还没产生进出站流量,却画出了实心堆叠柱,极易误导用户;
- 累计折线垂直跳崖:新安装或缺乏历史打点时,过去 20 多天折线在底部为 0 贴地飞行,到了“今日”点被强行赋值当月总计费累计,产生 90 度突兀断崖;
- 14 天硬截断脱节:预测折线在 14 天处戛然而止,看不到周期重置日,折线终点与上方 KPI 卡片的“预测总消耗”数值脱节;
- X 轴文字重叠:“今日”高亮标签与两端日期标签缺乏碰撞检测,在特定屏幕宽度下文字相互覆盖;
- 快速发布后又发现一处因函数遗漏导致的
applyFilter状态筛选按钮失效问题。
- 重构与解决方案:
- 建立统一账单周期坐标系:将 X 轴严格限定在节点的单个计费月
[cycleStart, cycleEnd](上一次重置日到下一次重置日,理论跨度 28~31 天),“今日”作为动态锚点; - 未来区间禁画柱状图:未来仅作为预测外推点位,
in_bytes/out_bytes严格为 0; - 预测折线全周期平滑外推:取消 14 天限制,预测虚线由今日点平滑延伸至
cycleEnd,确保终点数值与 KPI 预测 100% 对齐; - 冷启动拒绝贴地线:无打点的历史天数保持留白,折线从首个有效数据点起笔;
- Canvas 文本碰撞检测:常规日期与两端及今日标签间距小于 38px 时自动隐去,并在
v26.10.08.2迅速补回缺失的applyFilter交互逻辑。
- 建立统一账单周期坐标系:将 X 轴严格限定在节点的单个计费月
Journal 2: 版本规范对齐 —— 转向 SemVer 三段式标准
- 覆盖版本:
v26.1008.1 - 问题背景:
原本计划采用四段式版本规范(如
v26.10.08.1)。但我发现 [[Komari]] 核心插件管理面板采用的是标准语义化版本解析器(SemVer),无法识别第 4 位小版本,直接导致版本号被截断,插件市场无法正常触发新版本更新检测。 - 重构与解决方案:
- 全面转向兼容标准 SemVer 的三段式版本架构:
Major.Minor.Patch(即年.月日.修订号,如26.1008.1); - 兼顾了发布日期的语义可读性与包管理器的版本比较逻辑,并在 CI 流水线中实现了自动更新
v1.json元数据。
- 全面转向兼容标准 SemVer 的三段式版本架构:
Journal 3: 前台悬浮小组件(Floating Widget)诞生与无侵入式注入
- 覆盖版本:
v26.1008.1v26.1008.4 - 问题背景: 流量预测和耗尽告警原来只能在后台管理页或独立公开页查看,用户在前台浏览机器状态时感知滞后。但如果直接在首页顶部导航栏注入额外按钮,又会破坏前台界面的纯净感与排版;同时,最初的注入代码还会错误地在管理后台重复出现,且对于新接入(总累计为 0)的节点在时序计算中存在漏算。
- 重构与解决方案:
- 前台轻量注入:通过后端插件钩子向前台客户端动态注入极简右下角悬浮小组件(Floating Widget);
- 顶部无侵入与单一出口:坚持首页顶部无侵入原则;浮层窗口顶部仅保留关闭按钮(
✕),底部保留唯一的「查看完整图表 ↗」跳转出口,避免双入口视觉混淆; - 插件级开关:在
komari-plugin.json中增加enable_floating_widget配置项(默认开启),赋予管理员自由开关权限; - 后台智能排除 & 零流量修复:自动判断当前 URL,禁止在 Admin 管理后台渲染小组件;打通
GET /api/recent/:uuid实时同步物理总累计,修复零流量节点的基准对齐。
Journal 4: 悬浮窗交互与样式深度打磨 —— 拖拽、隔离与事件防冲突
- 覆盖版本:
v26.1008.5v26.1008.7 - 问题背景:
小组件上线后暴露了多处前端细节冲突:
- 悬浮按钮固定在右下角容易遮挡宿主网页内容,且无法一眼感知整体告警状态;
- 注入的 CSS 样式受宿主全局样式污染,卡片边框、内边距被破坏;若样式表中声明了带有
!important的固定坐标,会导致 JS 动态计算的left/top拖拽位置被强行锁死,使得按钮无法拖动; - SVG 图标子元素拦截了 Pointer 事件,导致拖拽中 target 错位;同时遮罩点击和关闭按钮偶现失效。
- 重构与解决方案:
- 告警呼吸光圈与自由拖拽:将按钮重构为紧凑的正方形图标,外边框随全节点最高告警状态动态渲染(红/黄/绿),支持拖拽至屏幕任意位置并记忆坐标;
- CSS 隔离与样式解耦:样式表只定义
position: fixed !important;,将定位赋值完全交由 JS 动态计算,彻底解决拖拽定位死锁;提升 CSS 选择器特异性并清理卡片默认边框,恢复清爽间距; - 事件防穿透与状态切换:为图标子元素添加
pointer-events: none;设定 4px 移动位移阈值以精确区分“点击展开”与“拖拽位移”;引入统一的.nf-open状态类,保证遮罩背景与右上角✕均能 100% 触发弹窗关闭。
Journal 5: 模板字符串反斜杠踩坑记与单节点智能聚焦
- 覆盖版本:
v26.1008.8v26.1009.1 - 问题背景:
为了让用户进入某台主机的实例详情页(
#/instance/:uuid或/instance/:uuid)时能自动聚焦该节点,我引入了路由监听逻辑,但紧接着遇到了一个极为隐蔽的严重 Bug:- 反斜杠被提前剥离导致崩溃:注入代码定义在服务端的 ES6 模板字符串(
`)中。当代码在 Komari 的 Goja 运行时中求值时,模板字符串内部所有的反斜杠被提前剥离,例如正则replace(/^#\/?/, "")变成了replace(/^#//?, ""),生成了//注释,直接把后续 JS 代码和括号完全注释吞噬!浏览器运行时抛出SyntaxError,导致小组件直接消失罢工。 - 此外,直接在实例页锁死单节点展示会导致用户无法点击切换“全部/预警”等状态筛选。
- 反斜杠被提前剥离导致崩溃:注入代码定义在服务端的 ES6 模板字符串(
- 重构与解决方案:
- 确立「模板字符串零反斜杠原则」:彻底禁止在客户端注入脚本中使用任何带有反斜杠的正则表达式,路径与 Hash 解析一律改用原生纯字符串方法(
split('/')、indexOf()、slice()); - 实例页动态高亮药丸:自动检测当前页面路由,识别到实例页时动态新增
📌 当前 (1)药丸并默认激活,同时完整保留“全部”、“预警”、“正常”药丸,让局部聚焦与全局切换互不干扰; - 多级容错匹配:支持精确 UUID、去除连字符比对以及前缀短 ID 匹配,并做
.trim()去除首尾空格防抖。
- 确立「模板字符串零反斜杠原则」:彻底禁止在客户端注入脚本中使用任何带有反斜杠的正则表达式,路径与 Hash 解析一律改用原生纯字符串方法(
Journal 6: 服务端 HTTP 响应流挂起排查 —— 别忘了 res.end()
- 覆盖版本:
v26.1009.2 - 问题背景:
偶发出现前台小组件或公开看板拉取
/api/plugin/net-forecast/overview接口时无休止处于 Loading 状态,最终提示网络请求超时。 - 根因诊断与修复:
- Komari 后端插件运行在基于 Goja 的 JS 运行时环境中。在自定义路由的
sendJSON(res, data, statusCode)方法中,此前仅仅调用了写入方法,遗漏了显式调用res.end(); - 这导致底层 HTTP 管道没有被正常关闭,连接一直处于挂起等待状态;
- 修复:在响应返回末尾补齐显式
res.end(JSON.stringify(data)),彻底消除连接假死。
- Komari 后端插件运行在基于 Goja 的 JS 运行时环境中。在自定义路由的
Journal 7: 极致首屏体验 —— SWR 零秒本地秒开与小组件双向直达
- 覆盖版本:
v26.1009.3 - 问题背景:
- 节点数量增加后,每次进入管理看板或公开页都需要全量聚合 720 小时的时序数据,全屏 Loading 阻塞遮罩导致用户每次刷新都要盯着空白加载框等待,体验沉重;
- 悬浮小组件里的节点卡片原本只是一张静态数据卡,用户在小组件看到某台节点爆流告警后,无法直接点击跳转,还得手动去后台翻找对应的机器详情页。
- 重构与解决方案:
- SWR 本地缓存与 0ms 瞬间秒开:
- 彻底废除全屏阻塞 Loading 遮罩;
- 基于 SWR(Stale-While-Revalidate)架构与
localStorage,刷新或二次打开页面时,0 毫秒瞬间还原所有节点卡片、KPI 状态与 30 天 Canvas 图表,用户感知等待时间直接归零;
- 非阻塞后台静默对齐:
- 页面秒开后,顶部展现极细渐变进度条与静默同步标记,后台自动完成时序计算后平滑热更新图表与数值;
- 流动微光骨架屏(Shimmer Skeleton):
- 无缓存首次访问时,0ms 呈现带微光流动的深色骨架占位卡片,杜绝白屏与跳动;
- 小组件卡片点击直达:
- 小组件节点卡片支持点击直达,智能适配 Komari 的 Hash 路由(
#/instance/:uuid)与 Path 路由(/instance/:uuid),卡片悬浮伴随呼吸蓝光与上浮微动效,并带有防重复点击保护。
- 小组件节点卡片支持点击直达,智能适配 Komari 的 Hash 路由(
- SWR 本地缓存与 0ms 瞬间秒开:
总结与演进脉络 从
v26.10.10到v26.1009.3,NetForecast 经历了一次从“单纯图表算法修正”到“整体前端工程与交互体验重塑”的蜕变:
- 核心算法层:通过统一计费周期坐标系,彻底解决了未来幽灵柱体与断崖折线;
- 前台表现层:推出了轻量级、防干扰、可拖拽的右下角悬浮小组件;
- 工程避坑层:踩平了 Goja 运行时中“模板字符串反斜杠剥离”和“未显式
res.end()挂起连接”两座隐蔽大坑;- 性能体验层:引入 SWR 与骨架屏,将数据密集型看板的等待感知压制到了极致。