给 zashboard 补上代理页文件夹:拖拽、列数、emoji 和一点迟到多年的吐槽

PR:https://github.com/Zephyruso/zashboard/pull/655

这次给 zashboard 的代理页补了一套我一直觉得 Mihomo / Clash 系 dashboard 早该有的交互:代理组文件夹。

事情的起点很朴素:代理组一多,页面就会变成一条很长很长的卡片流。大家都很认真地做延迟、图标、颜色、卡片动效、流量统计,但真正每天会用到的“把一堆策略组按用途收起来”反而常年缺位。媒体、基础选择、地区策略、端口专用、应用服务,明明脑子里就是几个抽屉,UI 上却经常只能一路往下翻。

所以这版做的不是更炫的 dashboard,而是更像一个工具台:

  • 代理组可以拖进文件夹,也可以从文件夹拖回根布局
  • 文件夹可以自定义 emoji、名称、宽度和高度
  • 代理页列数从原来的一列/两列扩展到 1-5 列
  • 每列独立排布,左边展开一个大文件夹时,不会把右边空白区域也同步撑高
  • 布局只保存少量 metadata,不引入重型 grid/layout 库,尽量不增加运行时负担
  • 节点原本的点击选择仍然保留,拖拽只在真正移动超过阈值后才接管

中间还有个很有意思的小插曲:一开始在 Codex 内置浏览器里拖拽是好的,但用户自己的 Chrome 里拖不动;后来把 Chrome 的拖拽修了,节点“点一下选择”又被误伤了。最后的处理是把交互边界拆清楚:pointer 按下不等于拖拽,只有移动超过 6px 才进入拖拽态;也只有发生了真实拖拽后,才阻止后续 click。这个细节很小,但对这种 dashboard 很关键,因为代理页既是列表,又是操作面板,拖拽和点击必须互不抢戏。

我觉得这类功能之所以值得吐槽,是因为它并不新潮,也不是技术上很难。它更像是“用久了以后一定会想要”的东西:把高频策略组放在眼前,把低频策略组收纳起来,按服务、地区、端口、特殊规则分区;需要比较时展开,需要清爽时折叠。很多 dashboard 已经在视觉上足够漂亮,但在“长期维护一份复杂 Mihomo 配置”的场景里,文件夹、列宽、拖拽排序、分组收纳这些才是真正省心的交互。

这版 PR 目前是 draft,主要是把可用形态先送上去。它不追求把代理页改成一个复杂编辑器,而是尽量保持轻:用现有 Vue 状态和 CSS 布局完成大部分事,只多存文件夹 meta、组归属、顺序和列数。后面如果维护者愿意收,大概还能继续打磨几个方向:更细的键盘可访问性、导入/导出布局、按 provider 自动生成文件夹、以及移动端上的更舒服拖放手势。

但至少这一步先证明了一件事:Mihomo 客户端的代理页不一定只能是一条长列表。它可以更像一个可整理的工作台。