- 「公网服务端」新增 Nginx 启停控制(Agent 0.15.2,停止带二次确认) - frps 启动失败不再误报成功,并增强启动诊断 - frps vhost 端口禁止 80/443,避免与 VPS 上 Nginx 冲突 - 旧服务端配置的 tcp_mux / login_fail_exit 默认值补齐 - 新增安全审查、页面布局方案与场景操作文档
10 KiB
「公网服务端」页面排版与结构调整方案
日期: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:低风险整理(建议先做)
不改信息架构,只修可读性与一致性。
- 修正 86-361 行的缩进,使层级与 DOM 一致(纯格式)
- 修正 ①②③④⑤ 注释编号,与渲染顺序对齐;或直接删掉编号,避免误导
- 长单行字段拆行(Nginx / frps 运行时两张卡)
- 端口监听卡的
✓/✗换成n-icon(如CheckmarkOutline/CloseOutline) - 把 VPS 资源 / VPS 证书从
stats-row移到独立的section-card容器,去掉grid-column: span 3特判 - 工具栏按三级重组:
启动/停止(主)→查看 / 日志 / 测速 / 校验 / 编辑(次级)→删除(危险,右侧分离)
预期:不改变用户可见的信息,但代码可读性与操作层级明显改善。
方案 B:信息架构调整(推荐)
-
消除重复详情:主区保留完整详情,把「查看」弹窗改为「深度诊断」并只保留主区没有的内容(延迟曲线、代理列表、连接日志),或直接删除该入口。二选一,不要并存。
-
主区改 tab:把 ①~⑤ 收进
n-tabs,例如概览:stats-row + VPS 资源 / 证书环境与依赖:dep-grid 三张卡运行控制:控制网格两张卡日志与输出:现有输出与日志卡
这样主区高度从"5 屏"收敛到"1 屏 + 按需切换",与本页"左侧选服务端、右侧看状态"的用法一致。
-
侧栏高度自适应:
.server-sidebar__list去掉固定max-height,改由父级align-items: start与页面滚动统一处理,避免双滚动。 -
选中态加强:在现有边框基础上加左侧 2px 强调条或背景色差,提升深色主题下的辨识度。
方案 C:结构重构(收益最大,风险也最高)
- 抽公共组件
ListDetailLayout(sidebar + detail 网格),由本页与 DdnsView 共用,消除 C2 的重复实现。 - 拆分本页为多个子组件,建议边界:
ServerListSidebar.vueServerOverviewPanel.vue(stats + VPS 资源/证书)ServerDependencyPanel.vueServerControlPanel.vue(生命周期 + frps 控制)ServerFormModal.vue(225 行表单)ServerLogsPanel.vue
- 清理 C3 的历史迁移样式段,确认无引用后合并去重。
这一步做完,单文件预计从 2244 行降到 400 行以内,但需要回归测试本页全部交互(安装 Agent、切换传输模式、下发 frps 配置、启停 frps、轮换证书)。
五、建议的推进顺序
| 阶段 | 内容 | 风险 | 可独立上线 |
|---|---|---|---|
| 第一步 | 方案 A 全部 6 项 | 低(纯格式与样式) | 是 |
| 第二步 | 方案 B 的 1、2 项(去重复详情 + 主区 tab) | 中(改交互路径) | 是 |
| 第三步 | 方案 B 的 3、4 项 | 低 | 是 |
| 第四步 | 方案 C 拆分 | 中高(涉及多组件) | 是,建议按组件逐个剥离 |
六、不做的事
为避免过度重构,以下不在本次范围内:
- 不改后端接口:本次全部为前端结构与样式调整。
- 不合并「公网服务端」与「公网反代」两个页面:两者职责不同(一个管 Agent/frps 主机,一个管域名路由),页面之间已有
.entrance-row引导,保持独立。 - 不改动
statusAlert互斥提示机制与EmptyState/LoadError的既有约定。 - 不动
n-modal的字段与提交逻辑:方案 C 拆分时只搬移结构,不重写表单校验。
七、验证方式
每阶段完成后需要确认:
npm run typecheck与npm run build通过- 在 3 档宽度下目视核对布局:≥1280px(双列)、1100px(切换单列断点)、≤760px(移动端)
- 深色 / 浅色两套主题下检查选中态、告警、徽标对比度
- 关键交互回归:切换服务端、安装/升级 Agent、切换传输模式(tunnel / https-pin / http)、下发 frps 配置、启停 frps、打开日志