本次重构对 CMPP Gateway 的 Web UI 进行了全面升级,采用现代化的设计理念和 Go 官方推荐的模板管理方式,大幅提升了用户体验和代码可维护性。
之前的问题:
- 使用过时的 Bootstrap 3.3.5(2015年版本)
- 使用不安全的 HTTP 协议 CDN(bootcss.com)
- 缺少现代化 UI 组件和响应式设计
现在的改进:
- ✅ 升级到 Bootstrap 5.3.2(最新稳定版)
- ✅ 使用 HTTPS + SRI(子资源完整性)保证安全性
- ✅ 引入 Bootstrap Icons 图标库
- ✅ 使用 jsdelivr CDN(更可靠、更快速)
之前的问题:
- 每个 HTML 文件都重复导航栏、头部、脚部代码
- 代码冗余,维护困难
- 模板直接在根目录,结构混乱
现在的架构:
templates/
├── layouts/ # 布局模板
│ └── base.html # 基础布局(包含 HTML 骨架)
├── partials/ # 可复用组件
│ ├── navbar.html # 导航栏
│ └── footer.html # 页脚
└── pages/ # 页面内容
├── index.html # 首页
├── list_message.html # 下发记录
└── list_mo.html # 上行记录
优势:
- 遵循 DRY(Don't Repeat Yourself)原则
- 修改导航栏只需编辑一个文件
- 清晰的目录结构,便于维护
httpserver.go 的新架构:
// 全局模板实例
var templates *template.Template
// 初始化模板,添加辅助函数
func initTemplates() error {
funcMap := template.FuncMap{
"add": func(a, b int) int { return a + b },
"sub": func(a, b int) int { return a - b },
"mul": func(a, b int) int { return a * b },
"eq": func(a, b interface{}) bool { return a == b },
"pageRange": func(current, total int) []int {
// 生成分页范围(最多5页)
// ...
},
}
// 加载所有模板文件
templates = template.New("").Funcs(funcMap)
// 解析 layouts, partials, pages 目录下的所有 .html 文件
}关键特性:
- 一次性加载所有模板,提高性能
- 自定义模板函数支持数学运算和分页
- 保留旧模板系统作为 fallback(向后兼容)
新增功能:
-
📊 实时统计卡片
- 下发总数(蓝色)
- 成功数量(绿色)
- 失败数量(红色)
- 上行总数(青色)
-
📱 优化的发送表单
- 实时字符计数
- 表单验证(手机号格式、必填项)
- Ajax 提交,无页面刷新
- Toast 提示反馈
-
🔗 连接状态显示
- CMPP 服务器状态
- Redis 缓存状态
- 实时状态指示灯
-
⚡ 快捷操作面板
- 快速跳转到下发/上行记录
新增功能:
-
🔍 高级过滤器
- 按号码过滤
- 按状态过滤
- 按内容关键词搜索
-
📈 统计概览卡片
- 总记录数
- 当前页码
- 总页数
-
📄 改进的分页系统
- 智能页码范围(最多显示5页)
- 首页/尾页禁用状态
- 显示记录范围提示
-
🎨 美化的表格
- 状态徽章(成功/失败/等待)
- 图标增强可读性
- 悬停高亮效果
- 空状态友好提示
-
🔄 自动刷新
- 下发记录:15秒自动刷新
- 上行记录:20秒自动刷新
- 用户交互时自动停止
移动端优化:
- 📱 导航栏折叠菜单
- 📊 统计卡片自动堆叠
- 📄 表格水平滚动
- 🔘 按钮自适应大小
适配屏幕:
- 手机:< 768px
- 平板:768px - 992px
- 桌面:> 992px
交互优化:
- ✨ 卡片悬停动画(阴影加深)
- 🎯 按钮图标 + 文字组合
- 🎨 语义化颜色系统
- 📍 面包屑导航高亮当前页
- 💬 友好的错误提示
可访问性:
- 🖱️ 键盘导航支持
- 🔤 语义化 HTML 标签
- 🎨 高对比度颜色
- 📖 屏幕阅读器友好
基础布局(base.html):
<!DOCTYPE html>
<html>
<head>
<title>{{template "title" .}} - CMPP Gateway</title>
{{template "head" .}}
</head>
<body>
{{template "navbar" .}}
<main>{{template "content" .}}</main>
{{template "footer" .}}
{{template "scripts" .}}
</body>
</html>页面模板(例如 index.html):
{{define "title"}}首页{{end}}
{{define "head"}}<!-- 页面特定 CSS -->{{end}}
{{define "content"}}<!-- 页面内容 -->{{end}}
{{define "scripts"}}<!-- 页面特定 JS -->{{end}}首页数据:
struct {
ActivePage string // 当前激活页面
Stats map[string]int // 统计数据
Config *Config // 配置信息
DefaultSrc string // 默认源号码
}列表页数据:
struct {
ActivePage string // 当前激活页面
Data *[]SmsMes // 消息列表
Page pages.Page // 分页信息
}"add": func(a, b int) int { return a + b }
"sub": func(a, b int) int { return a - b }
"mul": func(a, b int) int { return a * b }
"eq": func(a, b interface{}) bool { return a == b }
"pageRange": func(current, total int) []int { /* ... */ }使用示例:
<!-- 计算记录序号:(当前页-1) × 每页大小 + 索引+1 -->
{{add (mul (sub $.Page.CurrentPage 1) $.Page.PageSize) (add $index 1)}}
<!-- 生成分页按钮 -->
{{range $i := pageRange .Page.CurrentPage .Page.TotalPage}}
<a href="?page={{$i}}">{{$i}}</a>
{{end}}代码保留了对旧模板系统的支持:
func index(w http.ResponseWriter, r *http.Request) {
// 如果新模板加载失败,使用旧模板
if templates == nil {
findTemplate(w, r, "index.html")
return
}
// 使用新模板系统
templates.ExecuteTemplate(w, "base.html", data)
}这意味着:
- ✅ 即使
templates/目录不存在,仍可使用旧 HTML 文件 - ✅ 可以平滑过渡,无需一次性迁移所有页面
- ✅ 生产环境降级保障
之前: 每次请求都解析模板文件
template.New(tpl).ParseFiles(tpl) // 每次请求都执行现在: 启动时一次性加载
// 启动时执行一次
templates.ParseFiles(allFiles...)
// 请求时直接使用
templates.ExecuteTemplate(w, "base.html", data)性能提升:
- 减少文件 I/O 操作
- 降低 CPU 解析开销
- 更快的响应时间
使用 jsDelivr CDN:
- ✅ 全球 CDN 节点
- ✅ 自动选择最近节点
- ✅ HTTP/2 支持
- ✅ 自动 Gzip 压缩
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
crossorigin="anonymous">防护:
- 防止 CDN 被劫持
- 确保文件完整性
- 防止中间人攻击
所有外部资源使用 HTTPS:
- ❌
http://cdn.bootcss.com/... - ✅
https://cdn.jsdelivr.net/...
# 构建项目
go build -mod=vendor
# 启动(使用默认 config.json)
./cmpp-gateway
# 或指定配置文件
./cmpp-gateway -c /path/to/config.json- 首页(控制面板):http://localhost:8000/
- 下发记录:http://localhost:8000/list_message
- 上行记录:http://localhost:8000/list_mo
修改导航栏:
编辑 templates/partials/navbar.html
修改页面样式:
编辑 templates/layouts/base.html 中的 <style> 标签
添加新页面:
- 在
templates/pages/创建新 HTML 文件 - 定义必需的模板块:
title,content - 在
httpserver.go添加路由处理函数
- 实现过滤功能的后端 API
- 添加导出功能(CSV/Excel)
- 实时 WebSocket 推送新消息
- 添加用户认证系统
- 统计图表(echarts/chart.js)
- 批量发送短信功能
- 定时任务调度
- 消息模板管理
- 多租户支持
- API 密钥管理
- 审计日志系统
- 国际化(i18n)
现象:
Warning: Failed to load new templates: no template files found
Falling back to old template system
解决:
- 确认
templates/目录存在 - 检查目录结构是否正确
- 确认有
.html文件在各子目录中
原因: CDN 访问受限
解决:
- 检查网络连接
- 尝试访问:https://cdn.jsdelivr.net/
- 如需离线,可下载 CSS/JS 到本地
原因: Redis 连接问题或数据库为空
解决:
- 检查 Redis 是否运行:
redis-cli ping - 检查配置文件中 Redis 地址
- 发送测试短信生成数据
本次 UI 重构实现了:
✅ 现代化界面 - Bootstrap 5 + 精美设计 ✅ 官方推荐架构 - Go 模板继承系统 ✅ 响应式设计 - 移动端友好 ✅ 性能优化 - 模板预加载 ✅ 安全增强 - HTTPS + SRI ✅ 向后兼容 - 平滑过渡 ✅ 可维护性 - 清晰的代码结构
代码位置:
- 模板文件:
templates/目录 - 后端逻辑:
gateway/httpserver.go - 旧版文件:根目录
*.html(保留作为备份)
相关文档:
- README.md - 项目总体说明
- CLAUDE.md - 开发指南
- DEPENDENCIES.md - 依赖管理
重构日期: 2025-10-29 作者: Claude Code 版本: 2.0.0