当前位置: 首页 > article >正文

AI书签管理工具开发全记录(十三):TUI基本框架搭建

文章目录

  • AI书签管理工具开发全记录(十三):TUI基本框架搭建
    • 前言 📝
    • 1.TUI介绍 🔍
    • 2. 框架选择 ⚙️
    • 3. 功能梳理 🎯
    • 4. 基础框架搭建⚙️
      • 4.1 安装
      • 4.2 参数设计
      • 4.3 绘制ui
        • 4.3.1 设计结构体
        • 4.3.2 创建头部
        • 4.3.3 创建主体
        • 4.3.4 创建日志栏
        • 4.3.5 创建整体布局
        • 4.3.6 创建启动函数
        • 4.3.6 对接cobra命令行
    • 5.效果测试 ✅

AI书签管理工具开发全记录(十三):TUI基本框架搭建

前言 📝

在上一篇文章中,我们实现了MCP查询集成,集成了常用的查询场景,在支持MCP的客户端如cherry studio中可以查询书签数据了。但有时候,我们需要快速的浏览书签书签,没有比命令行的方式更快速的了,但是命令行操作太繁琐,所以我们本篇文章采用更进一步的TUI。

1.TUI介绍 🔍

TUI(Terminal User Interface) 是命令行工具与图形界面的完美融合体。不同于传统CLI需要记忆复杂指令的操作方式,TUI通过直观的文本界面组件(如菜单、列表、状态栏)实现可视化交互;相较于GUI应用,它又保留了终端操作的高效性与轻量级优势。经典的Linux工具如htopncduvim都证明了TUI在提升生产力方面的价值——无需离开终端窗口,即可实现键盘驱动的快速导航与操作。

在书签管理场景中,TUI能让我们通过方向键即时浏览收藏链接,用快捷键执行搜索/跳转/删除等操作,避免图形界面加载的延迟和命令行输入的低效。

2. 框架选择 ⚙️

在Go语言的TUI框架生态中,rivo/tview 以其组件化的设计强大的布局能力卓越的性能脱颖而出,成为我们构建书签管理TUI的首选。它提供了一套丰富且高度可定制的基础组件(如列表 List、表格 Table、文本框 TextView、表单 Form、模态框 Modal 等)和灵活的布局管理器(如 Flex, Grid, Pages),极大地简化了复杂终端界面的构建过程。其核心优势在于:

  1. 声明式布局:通过组合嵌套布局和组件,可以直观地构建出结构清晰、响应式的界面,适应不同终端尺寸。
  2. 高效渲染与键盘导航tview 采用智能渲染机制,确保界面更新流畅。它内置了强大且可自定义的键盘事件处理系统,让我们能够轻松为书签的浏览、选择、搜索、操作(打开、删除、编辑)定义直观的快捷键,实现真正的“键盘驱动”体验。
  3. 丰富的样式与主题:支持设置文本颜色、背景色、边框样式、标题等,允许我们为书签的不同状态(如已读/未读、分类)设计清晰的视觉区分。
  4. 活跃的社区与成熟度:作为Go领域最受欢迎的TUI库之一,tview 拥有良好的文档、活跃的社区支持和经过大量项目验证的稳定性。

选择 tview,意味着我们能高效地实现一个性能出色交互流畅视觉清晰的书签管理终端应用,完美契合我们追求快速浏览与操作的核心目标。接下来,我们将开始搭建基于 tview 的应用基础框架。

3. 功能梳理 🎯

在开始搭建基础框架前,我们先规划一下tui应用需求和布局

功能列表:

  • 需要搜索功能,可以快速搜索书签
  • 可以快速浏览器分类、书签

ui设计:

  • 最顶层是搜索框,可以输入关键词进行搜索
  • 中间是三栏数据,第一栏分类、第二栏书签、第三栏书签描述
  • 最下层是日志框,可以隐藏

4. 基础框架搭建⚙️

4.1 安装

go get -u github.com/rivo/tview

4.2 参数设计

需求:

  1. 启动时可以输入关键词,查询书签
  2. 可以关闭日志栏
// cmd/root.go:Execute
rootCmd.Flags().StringP("search", "s", "", "Search for a command")
rootCmd.Flags().BoolP("showlog", "l", false, "Show log panel")

4.3 绘制ui

4.3.1 设计结构体
// internal/tui/app.gotype TuiView struct {app             *tview.ApplicationsearchBox       *tview.InputFieldcategoryList    *tview.ListbookmarkList    *tview.ListdescriptionView *tview.TextViewlogView         *tview.TextViewmain            *tview.Flexmodal           *tview.Flexpages           *tview.Pagesfocusable       []tview.PrimitiveshowLog         boolfocusIndex      int
}
4.3.2 创建头部
// internal/tui/ui.gofunc (t *TuiView) CreateHeader() *tview.TextView {return tview.NewTextView().SetDynamicColors(true).SetTextAlign(tview.AlignCenter).SetText("[::b]AiBookMark[::-] [darkcyan] ← →:切换 ↑↓:导航 CTRL+F:搜索 /CTRL+R:重置 Q:退出")
}
4.3.3 创建主体
// internal/tui/ui.gofunc (t *TuiView) CreateCategoryList() *tview.List {t.categoryList = tview.NewList().ShowSecondaryText(true)t.categoryList.SetBorder(true).SetTitle(" 分类 ")t.categoryList.SetBorderColor(tcell.ColorWhite) // 添加默认边框颜色return t.categoryList
}func (t *TuiView) CreateBookmarkList() *tview.List {t.bookmarkList = tview.NewList().ShowSecondaryText(true)t.bookmarkList.SetBorder(true).SetTitle(" 书签 ")t.bookmarkList.SetBorderColor(tcell.ColorWhite) // 添加默认边框颜色return t.bookmarkList
}func (t *TuiView) CreateDescriptionView() *tview.TextView {t.descriptionView = tview.NewTextView().SetDynamicColors(true).SetScrollable(true).SetWrap(true)t.descriptionView.SetBorder(true).SetTitle(" 描述 ")t.descriptionView.SetBorderColor(tcell.ColorWhite) // 添加默认边框颜色return t.descriptionView
}func (t *TuiView) CreateMain() *tview.Flex {// 菜单列表t.CreateCategoryList()// 书签列表t.CreateBookmarkList()// 书签描述t.CreateDescriptionView()// 创建布局mainFlex := tview.NewFlex()mainFlex.AddItem(t.categoryList, 35, 0, true)mainFlex.AddItem(tview.NewFlex().AddItem(t.bookmarkList, 0, 1, true).AddItem(t.descriptionView, 0, 2, false), 0, 1, false)return mainFlex
}
4.3.4 创建日志栏
// internal/tui/ui.gofunc (t *TuiView) CreateLogs() *tview.TextView {t.logView = tview.NewTextView().SetDynamicColors(true).SetScrollable(true).SetWrap(false)t.logView.SetBorder(true).SetTitle(" 日志 ")return t.logView
}
4.3.5 创建整体布局
// internal/tui/ui.gofunc (t *TuiView) CreateMainFlex() *tview.Flex {mainFlex := tview.NewFlex()mainFlex.SetDirection(tview.FlexRow)// HeadermainFlex.AddItem(t.CreateHeader(), 3, 0, false)// 搜索框mainFlex.AddItem(t.CreateSearchBox(), 3, 0, false)// CategoryListmainFlex.AddItem(t.CreateMain(), 0, 1, false)if t.showLog {mainFlex.AddItem(t.CreateLogs(), 8, 10, false)}return mainFlex
}
4.3.6 创建启动函数
// internal/tui/app.go
func (t *TuiView) Run(searchKeyWord string, showLog bool) {t.showLog = showLog// 初始化应用程序t.app = tview.NewApplication()// enable鼠标t.app.EnableMouse(false)// 创建mainFlext.main = t.CreateMainFlex()// 初始化可聚焦组件列表t.focusable = []tview.Primitive{t.categoryList, t.bookmarkList, t.descriptionView}t.focusIndex = 0// 设置根节点t.app.SetRoot(t.main, true)// 设置焦点t.Focus(t.focusable[t.focusIndex])// 设置初始焦点组件的边框颜色if focusable, ok := t.focusable[t.focusIndex].(interface{ SetBorderColor(tcell.Color) }); ok {focusable.SetBorderColor(tcell.ColorSkyblue)}if err := t.app.Run(); err != nil {fmt.Println("TUI启动失败: " + err.Error())}
}
4.3.6 对接cobra命令行
// internal/tui/app.go// 获取搜索关键字
searchKeyword, _ := cmd.Flags().GetString("search")
// 是否显示日志
show, _ := cmd.Flags().GetBool("showlog")
tui := tui.TuiView{}
tui.Run(searchKeyword, show)

5.效果测试 ✅

运行

go run main.go

image.png

带日志启动
image.png

基本框架搭建完毕,后续就是从数据库中获取数据,渲染到终端上。


往期系列

  • Ai书签管理工具开发全记录(一):项目总览与技术蓝图
  • Ai书签管理工具开发全记录(二):项目基础框架搭建
  • AI书签管理工具开发全记录(三):配置及数据系统设计
  • AI书签管理工具开发全记录(四):日志系统设计与实现
  • AI书签管理工具开发全记录(五):后端服务搭建与API实现
  • AI书签管理工具开发全记录(六):前端管理基础框框搭建 Vue3+Element Plus
  • AI书签管理工具开发全记录(七):页面编写与接口对接
  • AI书签管理工具开发全记录(八):Ai创建书签功能实现
  • AI书签管理工具开发全记录(九):用户端页面集成与展示
  • AI书签管理工具开发全记录(十):命令行中结合ai高效添加书签
  • AI书签管理工具开发全记录(十一):MCP集成
  • # AI书签管理工具开发全记录(十二):MCP集成查询
http://www.lryc.cn/news/2403398.html

相关文章:

  • <2>-MySQL库的操作
  • Apache DolphinScheduler 和 Apache Airflow 对比
  • 初识结构体,整型提升及操作符的属性
  • 检测到 #include 错误。请更新 includePath。已为此翻译单元(D:\软件\vscode\test.c)禁用波形曲线
  • python --导出数据库表结构(pymysql)
  • 如何自动部署GitLab项目
  • 在 Windows 系统上运行 Docker 容器中的 Ubuntu 镜像并显示 GUI
  • 基于 COM 的 XML 解析技术(MSXML) 的总结
  • 多分辨率 LCD 的 GUI 架构设计与实现
  • 2025年,百度智能云打响AI落地升维战
  • Seed1.5-VL登顶,国产闭源模型弯道超车丨多模态模型5月最新榜单揭晓
  • SON.stringify()和JSON.parse()之间的转换
  • 【学习笔记】构造函数+重载相关
  • JVM——打开JVM后门的钥匙:反射机制
  • 第3章——SSM整合
  • VTK 显示文字、图片及2D/3D图
  • 小白如何在cursor中使用mcp服务——以使用notion的api为例
  • 引领AI安全新时代 Accelerate 2025北亚巡展·北京站成功举办
  • 为什么说数列是特殊的函数
  • 解决uniapp开发app map组件最高层级 遮挡自定义解决底部tabbar方法
  • 96. 2017年蓝桥杯省赛 - Excel地址(困难)- 进制转换
  • PPT转图片拼贴工具 v1.0
  • 大模型在脑梗塞后遗症风险预测及治疗方案制定中的应用研究
  • Qwen2.5-VL - 模型结构
  • 【QT常用技术讲解】多线程执行后台命令行的两种方式(后台运行和返回打印信息)
  • 【行驶证识别成表格】批量OCR行驶证识别与Excel自动化处理系统,行驶证扫描件和照片图片识别后保存为Excel表格,基于QT和华为ocr识别的实现教程
  • Linux--进程的状态
  • (nice!!!)(LeetCode每日一题)2434. 使用机器人打印字典序最小的字符串(贪心+栈)
  • 008-libb64 你有多理解base64?-C++开源库108杰
  • 电子电路基础2(杂乱)