Files
Havline/docs/agent-view-layout-plan-2026-10-07.md
T
mrlee 2a0740a60f
CI / verify (push) Canceled after 0s
Docker Release / build-and-push (amd64, linux/amd64) (push) Canceled after 0s
Docker Release / build-and-push (arm64, linux/arm64) (push) Canceled after 0s
GitHub Release / release (push) Canceled after 0s
Docker Release / create-manifest (push) Canceled after 0s
chore(release): 发布 v1.9.2
- 「公网服务端」新增 Nginx 启停控制(Agent 0.15.2,停止带二次确认)
- frps 启动失败不再误报成功,并增强启动诊断
- frps vhost 端口禁止 80/443,避免与 VPS 上 Nginx 冲突
- 旧服务端配置的 tcp_mux / login_fail_exit 默认值补齐
- 新增安全审查、页面布局方案与场景操作文档
2026-10-07 19:26:02 +08:00

10 KiB
Raw Permalink Blame History

「公网服务端」页面排版与结构调整方案

日期:2026-10-07 对象:AgentView.vue(2244 行 / 136 KB) 性质:只出方案,不含代码改动 参考页面:DdnsView.vue、ProxyRemoteView.vue、FrpView.vue

一、现状测绘

页面当前的 DOM 骨架:

PageHeader(公网服务端 + 刷新)
├─ LoadError / EmptyState
└─ .agent-layout(grid: 260-320px | 1fr)
   ├─ aside.server-sidebar            服务端列表
   └─ div.agent-detail
      ├─ .server-toolbar              7 个操作按钮平铺
      ├─ n-alert                      状态提示(互斥)
      ├─ .entrance-row                公网反代入口引导
      ├─ ① section.stats-row          4 张指标卡 + VPS 资源卡 + VPS 证书卡
      ├─ ② section.dep-grid           3 张卡(Agent / Nginx / frps 运行时)
      ├─ ④③ .control-grid             2 张卡(生命周期 / frps 控制)
      └─ ⑤ HavlineCard                输出与日志(内部两个 tab)

另外 5 个 n-modal 集中在 template 尾部:
  frps.toml 预览、服务端表单(390-615,共 225 行)、日志、服务端详情、frps 配置

页面要做的事:服务端增删改查、Agent 生命周期、frps 控制、frps.toml 预览下发、VPS 资源与证书巡检、操作输出与日志。

二、同类页面参考

页面 布局 详情区组织 操作按钮
DdnsView.vue .ddns-layout + aside.task-sidebar + section.task-detail 头部 .task-detail__head + 若干 HavlineCard.detail-section 集中在头部,分三级:主操作(primary ghost)、次级(默认)、危险(error)
ProxyRemoteView.vue .proxy-layout + .proxy-detail stats-row + 2 张 section-card 数量少,未出现平铺
FrpView.vue 规则列表 + 弹窗 弹窗内分 tab —

全站通行模式:指标用 stats-row,内容用 HavlineCard.section-card,两者语义不同、不混用。这一点上「公网服务端」页是偏离的。

三、发现的问题

A. 信息架构

A1 同一份详情做了两套。 主区已经完整展示了状态、依赖、生命周期、日志,工具栏上的「查看」又打开一个 n-modal,里面是基本信息 / 服务器状态 / 延迟曲线 / 代理 / 连接日志(第 633-667 行)。两边字段重叠,用户不知道该点哪个,维护时也容易只改一边。

A2 区块编号与渲染顺序不符。 注释写着 <!-- ④ Agent 生命周期(SSH) + ③ frps 控制:两列并排 -->(第 239 行),但 ① ② 之后直接是 ④,编号失去导航作用,反而让人以为漏了 ③。

A3 主区没有内部导航。 .agent-detail 里纵向堆了 6 个区块,要看到「输出与日志」至少滚动 4-5 屏。左侧切服务端、右侧滚很久,是这个页面最明显的使用负担。

A4 stats-row 混装了两种语义的卡片。 4 张 .stat-card(指标)与 2 张 HavlineCard.section-card.vps-resource-card(内容)共用一个 4 列网格。样式里已经要靠特判来收拾:

/* 前四张卡每行三张(各占 2/6),VPS 资源与 VPS 证书各占 3/6 并排 */
/* VPS 资源:占满「环境与依赖」整行,避免单独占一格显得突兀 */
.dep-grid > .vps-resource-card { grid-column: span 3; }

注释本身就说明了"不协调"。

A5 工具栏 7 个操作完全平权。 第 76-83 行:启动/停止、查看、日志、测速、校验、编辑、删除并列,全部 size="small",其中「删除」是 quaternary type="error",与「测速」视觉权重接近。DdnsView 的做法是主操作 / 次级 / 危险三级分组,值得对齐。

B. 排版与代码可读性

B1 缩进错乱(DOM 正确)。 第 86 行起,「状态提示」到「输出与日志」的整段缩进比父级 .server-toolbar 浅两格,直到 第 360 行附近才恢复。实际层级是对的(</div> 在 361-362 行才闭合 .agent-detail / .agent-layout),但读代码时无法判断区块归属,后续改结构极易改错层级。

B2 单行过长。 Nginx / frps 运行时两张卡的字段全部写成单行,最长的超过 200 字符(例如 第 233 行的"启动命令")。diff、review 和合并冲突都不友好。

B3 图标体系不一致。 端口监听卡用文本符号 {{ port }} {{ portOn(port) ? '✓' : '✗' }}(第 134 行),页面其余位置统一用 n-icon。

B4 冗余字号规则。 .stat-card__value 定义了 30px(第 1841 行),但本页所有 stat-card 都加了 --sm(18px),30px 规则形同虚设,多半是从 FrpView 迁入时留下的。

C. 文件结构

C1 单文件职责过载。 2244 行承担 7 类功能,n-modal 表单就占 225 行。任何一处调整都要在 136 KB 的文件里定位。

C2 与 DDNS 页"同构"却各写一套。 第 25 行注释自己写明「与 DDNS 页(.ddns-layout / .task-sidebar)同构」,但类名与样式完全重复实现(.agent-layout/.server-sidebar vs .ddns-layout/.task-sidebar)。

C3 样式分两段来源。 第 2064 行有注释「以下样式随「公网服务端」列表与弹窗从内网穿透页迁入(2026-09-24)」,与前半段并存,存在历史迁移残留。

D. 交互细节

D1 侧栏高度写死。 .server-sidebar__list { max-height: 720px; overflow: auto; }(第 2221 行),服务端多时会出现"侧栏内部滚动 + 页面滚动"双重滚动。

D2 选中态偏弱。 .server-item--active 只有边框色与一圈 1px 阴影,在深色主题下辨识度有限。

D3 值得保留的部分。 EmptyState + LoadError + statusAlert(互斥最多一条)的设计是好的,不要在这次调整中丢掉。

四、优化方案

按"改动量 / 收益"排成三档,可分批做。

方案 A:低风险整理(建议先做)

不改信息架构,只修可读性与一致性。

  1. 修正 86-361 行的缩进,使层级与 DOM 一致(纯格式)
  2. 修正 ①②③④⑤ 注释编号,与渲染顺序对齐;或直接删掉编号,避免误导
  3. 长单行字段拆行(Nginx / frps 运行时两张卡)
  4. 端口监听卡的 ✓/✗ 换成 n-icon(如 CheckmarkOutline / CloseOutline)
  5. 把 VPS 资源 / VPS 证书从 stats-row 移到独立的 section-card 容器,去掉 grid-column: span 3 特判
  6. 工具栏按三级重组:启动/停止(主)→ 查看 / 日志 / 测速 / 校验 / 编辑(次级)→ 删除(危险,右侧分离)

预期:不改变用户可见的信息,但代码可读性与操作层级明显改善。

方案 B:信息架构调整(推荐)

  1. 消除重复详情:主区保留完整详情,把「查看」弹窗改为「深度诊断」并只保留主区没有的内容(延迟曲线、代理列表、连接日志),或直接删除该入口。二选一,不要并存。

  2. 主区改 tab:把 ①~⑤ 收进 n-tabs,例如

    • 概览:stats-row + VPS 资源 / 证书
    • 环境与依赖:dep-grid 三张卡
    • 运行控制:控制网格两张卡
    • 日志与输出:现有输出与日志卡

    这样主区高度从"5 屏"收敛到"1 屏 + 按需切换",与本页"左侧选服务端、右侧看状态"的用法一致。

  3. 侧栏高度自适应:.server-sidebar__list 去掉固定 max-height,改由父级 align-items: start 与页面滚动统一处理,避免双滚动。

  4. 选中态加强:在现有边框基础上加左侧 2px 强调条或背景色差,提升深色主题下的辨识度。

方案 C:结构重构(收益最大,风险也最高)

  1. 抽公共组件 ListDetailLayout(sidebar + detail 网格),由本页与 DdnsView 共用,消除 C2 的重复实现。
  2. 拆分本页为多个子组件,建议边界:
    • ServerListSidebar.vue
    • ServerOverviewPanel.vue(stats + VPS 资源/证书)
    • ServerDependencyPanel.vue
    • ServerControlPanel.vue(生命周期 + frps 控制)
    • ServerFormModal.vue(225 行表单)
    • ServerLogsPanel.vue
  3. 清理 C3 的历史迁移样式段,确认无引用后合并去重。

这一步做完,单文件预计从 2244 行降到 400 行以内,但需要回归测试本页全部交互(安装 Agent、切换传输模式、下发 frps 配置、启停 frps、轮换证书)。

五、建议的推进顺序

阶段 内容 风险 可独立上线
第一步 方案 A 全部 6 项 低(纯格式与样式) 是
第二步 方案 B 的 1、2 项(去重复详情 + 主区 tab) 中(改交互路径) 是
第三步 方案 B 的 3、4 项 低 是
第四步 方案 C 拆分 中高(涉及多组件) 是,建议按组件逐个剥离

六、不做的事

为避免过度重构,以下不在本次范围内:

  1. 不改后端接口:本次全部为前端结构与样式调整。
  2. 不合并「公网服务端」与「公网反代」两个页面:两者职责不同(一个管 Agent/frps 主机,一个管域名路由),页面之间已有 .entrance-row 引导,保持独立。
  3. 不改动 statusAlert 互斥提示机制与 EmptyState / LoadError 的既有约定。
  4. 不动 n-modal 的字段与提交逻辑:方案 C 拆分时只搬移结构,不重写表单校验。

七、验证方式

每阶段完成后需要确认:

  1. npm run typecheck 与 npm run build 通过
  2. 在 3 档宽度下目视核对布局:≥1280px(双列)、1100px(切换单列断点)、≤760px(移动端)
  3. 深色 / 浅色两套主题下检查选中态、告警、徽标对比度
  4. 关键交互回归:切换服务端、安装/升级 Agent、切换传输模式(tunnel / https-pin / http)、下发 frps 配置、启停 frps、打开日志