NetCmdRegister 应用开发详解(三):UI 界面设计与实现

本文最后更新于:2025年11月2日 晚上

NetCmdRegister 应用开发详解(三):UI 界面设计与实现

大家好!我是 NetCmdRegister 的开发者。在前两篇文章中,我们搭建了项目基础并深入理解了 Electron 的架构。今天,我们将重点探讨用户界面的设计与实现,这是用户与我们的应用直接交互的部分。

设计理念与用户体验

设计原则

在设计 NetCmdRegister 的界面时,我遵循了几个核心原则:

  1. 功能优先:界面服务于功能,每个元素都有明确用途
  2. 直观操作:用户无需学习就能理解如何操作
  3. 信息清晰:重要状态和反馈一目了然
  4. 视觉层次:通过布局和颜色建立清晰的信息层级

色彩系统设计

我选择了 Slate 色系 作为基础色调,原因如下:

  • 专业且不刺眼,适合长时间使用
  • 良好的对比度,确保可读性
  • 与现代开发工具风格一致

功能色系分配:

  • 🟢 绿色:成功状态、启动操作、发送功能
  • 🔴 红色:错误状态、停止操作、删除功能
  • 🔵 蓝色:信息性操作、导入功能
  • 🟣 紫色:特殊功能(定时发送)

HTML 结构深度解析

文档基础与元信息

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta author="jinbilianshao">
<title>NetCmdRegister - 网络命令注册器</title>
<script src="tailwindcss.js"></script>
<link rel="stylesheet" href="styles.css">
</head>

关键设置解析:

字符编码

  • UTF-8 确保中文字符正确显示
  • 支持多语言环境

视口设置

  • width=device-width 适配移动设备
  • initial-scale=1.0 防止默认缩放

Tailwind CSS 引入

  • 使用 CDN 版本简化部署
  • 无需构建步骤,适合小型项目

整体布局架构

1
2
3
4
5
6
<body class="bg-slate-50 font-sans text-slate-800 flex flex-col min-h-screen">
<div class="max-w-7xl mx-auto p-4 md:p-6 lg:p-8 flex-grow w-full">
<!-- 页面内容 -->
</div>
<footer><!-- 页脚 --></footer>
</body>

布局技术详解:

Flexbox 垂直布局

1
<body class="flex flex-col min-h-screen">
  • flex 启用弹性布局
  • flex-col 垂直方向排列
  • min-h-screen 最小高度为视口高度

响应式容器

1
<div class="max-w-7xl mx-auto p-4 md:p-6 lg:p-8">
  • max-w-7xl 最大宽度约束(~80rem)
  • mx-auto 水平居中
  • 响应式内边距:小屏幕 1rem,中屏幕 1.5rem,大屏幕 2rem

核心功能区域设计

1. 页面头部设计

1
2
3
4
<header class="text-center mb-6">
<h1 class="text-4xl font-bold text-slate-900">网络命令注册器</h1>
<p class="text-slate-500 mt-2">一个用于测试和调试 UDP 命令的工具</p>
</header>

设计考量:

  • 主标题:大字号加粗,建立视觉焦点
  • 副标题:较小字号,灰色降低视觉权重
  • 居中对齐:创建平衡的视觉感受
  • 底部外边距:与后续内容建立清晰分隔

2. 网格布局系统

1
2
3
4
5
6
7
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 h-full">
<!-- 左侧主要内容区 -->
<div class="lg:col-span-2 space-y-6">...</div>

<!-- 右侧日志区 -->
<div class="lg:col-span-1 space-y-4 flex flex-col">...</div>
</div>

响应式网格策略:

小屏幕布局(默认)

  • grid-cols-1:单列布局
  • 垂直堆叠所有内容
  • 确保移动设备上的可用性

大屏幕布局(≥1024px)

  • lg:grid-cols-3:三列网格
  • 左侧占 2/3,右侧占 1/3
  • 充分利用宽屏空间

间距系统

  • gap-6:元素间 1.5rem 间距
  • space-y-6:垂直方向 1.5rem 间距
  • 建立清晰的视觉分组

组件级设计详解

服务控制区域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<section class="bg-white p-6 rounded-xl shadow-md ring-1 ring-slate-200">
<h2 class="text-2xl font-semibold text-slate-700 mb-4 border-b border-slate-200 pb-3">服务控制</h2>
<div class="flex items-center justify-between flex-wrap gap-4">
<!-- 状态指示 -->
<div class="flex items-center space-x-3">
<div id="udp-status-indicator" class="w-4 h-4 rounded-full bg-red-500 transition-colors"></div>
<span id="udp-status-text" class="font-semibold text-red-500 transition-colors">服务已停止</span>
</div>
<!-- 控制输入和按钮 -->
<div class="flex items-center space-x-4">
<div class="flex items-center">
<label for="local-port" class="mr-2 text-sm font-medium text-slate-600">本地监听端口:</label>
<input type="number" id="local-port" value="8001"
class="w-24 rounded-md border-slate-300 shadow-sm p-2 text-sm focus:ring-slate-500 focus:border-slate-500">
</div>
<button id="toggle-udp-btn" class="bg-green-600 text-white py-2 px-4 rounded-md font-bold hover:bg-green-700 transition-all shadow-md flex items-center space-x-2">
<!-- SVG 图标 -->
<span>启动服务</span>
</button>
</div>
</div>
</section>

组件设计要点:

视觉容器

  • bg-white 白色背景突出内容
  • rounded-xl 大圆角现代感
  • shadow-md 适度阴影创造深度
  • ring-1 ring-slate-200 细边框定义边界

状态指示器

  • 圆形设计:w-4 h-4 rounded-full
  • 颜色语义:红色停止,绿色运行
  • transition-colors 平滑状态切换

表单控件

  • 标签使用 text-sm font-medium 确保可读性
  • 输入框 rounded-md border-slate-300 统一边框样式
  • focus:ring-slate-500 聚焦状态视觉反馈

命令列表 Tab 系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<section class="bg-white rounded-xl shadow-md ring-1 ring-slate-200">
<div class="border-b border-slate-200">
<nav class="-mb-px flex space-x-6 px-6" aria-label="Tabs">
<button id="tab-list-btn" class="tab-btn active shrink-0 border-b-2 py-4 px-1 text-base font-medium" data-tab="list">
命令列表
</button>
<button id="tab-add-btn" class="tab-btn shrink-0 border-b-2 py-4 px-1 text-base font-medium" data-tab="add">
添加/编辑
</button>
</nav>
</div>

<div class="p-6">
<!-- Tab 内容区域 -->
</div>
</section>

Tab 设计技术:

导航栏布局

  • -mb-px 负边距与内容区域边框重叠
  • flex space-x-6 水平等间距排列
  • shrink-0 防止按钮被压缩

激活状态管理 通过 CSS 类控制激活状态:

1
2
3
4
.tab-btn.active {
border-color: #4f46e5; /* indigo-600 */
color: #4f46e5; /* indigo-600 */
}

命令添加表单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="tab-panel-add" class="hidden">
<div class="space-y-4 max-w-md mx-auto">
<div>
<label for="command-name" class="block text-sm font-medium text-slate-600">命令名称</label>
<input type="text" id="command-name" placeholder="例如: 设备重启"
class="mt-1 block w-full rounded-md border-slate-300 shadow-sm p-2 focus:ring-slate-500 focus:border-slate-500">
</div>
<div>
<label for="command-payload" class="block text-sm font-medium text-slate-600">命令内容 (十六进制)</label>
<textarea id="command-payload" rows="3" placeholder="例如: 01 02 03 FF 0A"
class="mt-1 block w-full rounded-md border-slate-300 shadow-sm p-2 focus:ring-slate-500 focus:border-slate-500"></textarea>
</div>
<button id="add-command-btn" class="w-full bg-slate-600 text-white py-2 px-4 rounded-md font-bold hover:bg-slate-700 transition-colors shadow-md flex items-center justify-center space-x-2">
<!-- SVG 图标 -->
<span>添加/更新命令</span>
</button>
</div>
</div>

表单设计最佳实践:

标签关联

  • for 属性与 id 对应,提高可访问性
  • block 显示确保标签独占一行

输入框设计

  • mt-1 在标签和输入框间创建间距
  • w-full 充分利用可用宽度
  • p-2 充足的内边距便于点击

按钮设计

  • w-full 全宽按钮,移动设备友好
  • flex items-center justify-center 图标文字居中
  • space-x-2 图标文字间距

命令列表管理

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="tab-panel-list">
<div class="flex items-center justify-between bg-slate-100 p-2 rounded-md mb-3">
<div class="flex items-center space-x-2">
<input type="checkbox" id="select-all-checkbox"
class="h-4 w-4 rounded border-slate-300 text-slate-600 focus:ring-slate-500">
<label for="select-all-checkbox" class="text-sm font-medium text-slate-600">全选</label>
</div>
<div class="flex items-center space-x-2">
<!-- 操作按钮组 -->
</div>
</div>
<ul id="registered-commands-list" class="space-y-2 min-h-[10rem] max-h-64 overflow-y-auto custom-scrollbar border p-2 rounded-md bg-slate-50"></ul>
</div>

列表管理功能:

工具栏设计

  • bg-slate-100 浅灰色背景区分功能区域
  • flex justify-between 左右分组布局
  • space-x-2 紧凑按钮间距

列表容器

  • min-h-[10rem] 最小高度确保布局稳定
  • max-h-64 最大高度防止过度增长
  • custom-scrollbar 自定义滚动条样式

命令发送区域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<section class="bg-white p-6 rounded-xl shadow-md ring-1 ring-slate-200">
<h2 class="text-2xl font-semibold text-slate-700 mb-4 border-b border-slate-200 pb-3">命令发送</h2>
<div class="space-y-4">
<!-- 目标地址输入 -->
<div class="flex items-end justify-between space-x-4">
<div class="flex-grow grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="dest-ip" class="block text-sm font-medium text-slate-600">目标IP地址</label>
<input type="text" id="dest-ip" value="127.0.0.1"
class="mt-1 block w-full rounded-md border-slate-300 shadow-sm p-2 focus-visible:outline-indigo-500">
</div>
<div>
<label for="dest-port" class="block text-sm font-medium text-slate-600">目标端口</label>
<input type="number" id="dest-port" value="8000"
class="mt-1 block w-full rounded-md border-slate-300 shadow-sm p-2 focus-visible:outline-indigo-500">
</div>
</div>
<button id="send-selected-btn" class="bg-green-600 text-white h-10 px-6 rounded-md font-bold hover:bg-green-700 transition-colors shadow-md flex items-center justify-center space-x-2 flex-shrink-0">
<!-- 发送图标 -->
<span>发送所选</span>
</button>
</div>

<hr class="border-slate-200">

<!-- 定时发送控制 -->
<div class="flex items-end justify-between space-x-4">
<div class="flex-grow">
<label for="send-interval-input" class="block text-sm font-medium text-slate-600">定时发送间隔 (毫秒)</label>
<input type="number" id="send-interval-input" value="1000"
class="mt-1 block w-full rounded-md border-slate-300 shadow-sm p-2 focus-visible:outline-indigo-500">
<!-- 警告信息 -->
<div id="interval-warning" class="hidden items-center space-x-1 text-xs text-orange-500 mt-1">
<!-- 警告图标 -->
<span>低于20ms的间隔可能不准确并大量消耗CPU。</span>
</div>
</div>
<button id="toggle-scheduled-send-btn" class="bg-indigo-600 text-white h-10 px-6 rounded-md font-bold hover:bg-indigo-700 transition-colors shadow-md flex items-center justify-center space-x-2 flex-shrink-0">
<!-- 播放/停止图标 -->
<span id="scheduled-send-btn-text">开始定时</span>
</button>
</div>
</div>
</section>

发送功能设计:

网格布局适配

  • grid grid-cols-1 md:grid-cols-2 响应式网格
  • 小屏幕单列,中屏幕双列
  • 充分利用水平空间

功能分区

  • hr 元素视觉分隔常规发送和定时发送
  • 不同的按钮颜色区分功能类型

交互反馈

  • 动态显示的警告信息
  • 按钮状态变化反映操作模式

实时日志显示

1
2
3
4
5
6
7
8
9
10
11
<section class="bg-white p-6 rounded-xl shadow-md ring-1 ring-slate-200 flex flex-col">
<div class="flex justify-between items-center border-b border-slate-200 pb-3 mb-4">
<h2 class="text-2xl font-semibold text-slate-700">实时日志</h2>
<button id="clear-log-btn" class="bg-red-600 text-white py-1 px-3 rounded-md font-bold hover:bg-red-700 transition-colors shadow-sm text-sm">
清空日志
</button>
</div>
<div id="log-container" class="bg-slate-800 text-slate-200 p-4 rounded-md font-mono text-sm shadow-inner overflow-y-auto custom-scrollbar max-h-[680px] min-h-[680px]">
<div id="log-empty-state" class="flex items-center justify-center h-full text-slate-700">日志为空</div>
</div>
</section>

日志区域设计:

标题栏布局

  • flex justify-between 标题和按钮两端对齐
  • border-b 底部边框视觉分隔

日志容器

  • bg-slate-800 深色背景减少视觉疲劳
  • font-mono 等宽字体便于阅读十六进制
  • max-h-[680px] min-h-[680px] 固定高度确保布局稳定

自定义样式与优化

滚动条美化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.custom-scrollbar::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background-color: rgba(156, 163, 175, 0.6);
border-radius: 6px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background-color: rgba(107, 114, 128, 0.8);
}
.custom-scrollbar::-webkit-scrollbar-track {
background: transparent;
}

滚动条设计考量:

  • 适当宽度不影响内容显示
  • 半透明设计融入整体风格
  • 悬停状态提供交互反馈

Tab 组件样式

1
2
3
4
5
6
7
8
9
10
11
12
.tab-btn {
border-color: transparent;
color: #475569; /* slate-600 */
}
.tab-btn:hover {
border-color: #cbd5e1; /* slate-300 */
color: #1e293b; /* slate-800 */
}
.tab-btn.active {
border-color: #4f46e5; /* indigo-600 */
color: #4f46e5; /* indigo-600 */
}

状态管理策略:

  • 默认状态:透明边框,中等灰色文字
  • 悬停状态:显示边框,深色文字
  • 激活状态:品牌色边框和文字

图标系统设计

SVG 图标使用

在整个界面中,我使用了统一的 SVG 图标系统:

播放图标(服务控制)

1
2
3
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
</svg>

添加图标(命令添加)

1
2
3
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>

图标设计原则:

  • 统一尺寸:h-5 w-5(20×20px)
  • 当前颜色:fill-currentColor 继承文字颜色
  • 简洁明了:避免过度复杂的图形

响应式设计策略

断点系统

Tailwind CSS 使用移动优先的断点系统:

  • 默认:移动设备样式(< 768px)
  • md:中等屏幕(≥ 768px)
  • lg:大屏幕(≥ 1024px)
  • xl:超大屏幕(≥ 1280px)

响应式模式示例

网格布局响应

1
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">

间距响应

1
<div class="p-4 md:p-6 lg:p-8">

显示隐藏响应

1
<div class="hidden md:block">

可访问性考虑

语义化 HTML

  • 使用 sectionnavheader 等语义化标签
  • 为 Tab 导航添加 aria-label="Tabs"
  • 表单控件正确关联 labelinput

键盘导航

  • 所有功能按钮都可键盘访问
  • 表单控件有清晰的聚焦状态
  • Tab 顺序符合用户预期

颜色对比度

  • 文本与背景有足够对比度
  • 状态颜色有明确的语义含义
  • 不单纯依赖颜色传递信息

性能优化考虑

CSS 优化

  • 使用 Tailwind CSS 的实用类,减少自定义 CSS
  • 内联关键样式,减少 HTTP 请求
  • 利用浏览器缓存静态资源

布局稳定性

  • 为动态内容容器设置 min-height
  • 使用 flex-shrink-0 防止重要元素被压缩
  • 为滚动容器设置固定高度

开发工作流建议

组件化思维

虽然这是一个单文件 HTML,但在开发时应保持组件化思维:

  1. 功能区域分离:每个 section 都是独立的组件
  2. 样式模块化:相关样式集中管理
  3. 状态独立:每个组件管理自己的状态

调试技巧

浏览器开发者工具

  • 使用元素检查器调试布局
  • 网络面板监控资源加载
  • 控制台查看 JavaScript 错误

响应式测试

  • 使用浏览器设备模拟器
  • 测试不同屏幕尺寸下的表现
  • 验证交互状态的视觉反馈

结语

通过本章的详细讲解,我们深入了解了 NetCmdRegister 用户界面的设计思路和实现细节。我们涵盖了:

  1. 整体布局架构:响应式网格系统和容器设计
  2. 组件级设计:每个功能区域的详细实现
  3. 交互设计:状态管理、反馈机制和用户体验
  4. 视觉设计:色彩系统、图标设计和样式优化
  5. 技术实现:Tailwind CSS 的高级用法和自定义样式

这些设计决策共同创造了一个既美观又实用的用户界面,为后续的功能实现奠定了坚实的基础。

在下一篇文章中,我们将深入探讨渲染进程的核心逻辑,学习如何让这个静态界面变得生动起来,实现完整的用户交互功能。

下一篇预告:《NetCmdRegister 应用开发详解(四):渲染进程的核心逻辑》——我们将学习如何使用 JavaScript 实现界面交互、状态管理和数据持久化。


NetCmdRegister 应用开发详解(三):UI 界面设计与实现
https://jinbilianshao.github.io/2025/11/02/NetCmdRegister-应用开发详解(三):UI-界面设计与实现/
作者
连思鑫
发布于
2025年11月2日
许可协议