Private
Public Access
1
0
Files
u-desk/docs/04-功能迭代/GO-DESK-2.数据库客户端/设计文档/功能设计/表结构查看功能设计.md

29 KiB
Raw Blame History

表结构查看功能设计

设计日期2025-01-28
设计范围MySQL、Redis、MongoDB 表结构查看界面设计
状态:设计阶段


设计概览

表结构查看功能提供统一的界面查看不同数据库类型的结构信息,支持:

  • MySQL:表字段详情、索引信息
  • MongoDB:文档示例、字段统计、索引信息
  • RedisKey 类型、TTL、值预览、长度统计

核心特性

  • 统一的对话框界面
  • 根据数据库类型自动适配展示内容
  • 支持 Tab 切换不同信息视图
  • 表格、JSON 等多种展示方式
  • 响应式设计,适配不同屏幕尺寸

一、功能概述

表结构查看功能允许用户查看不同数据库类型的结构信息:

  • MySQL:表字段信息、索引信息
  • MongoDB:集合文档示例、字段统计、索引信息
  • RedisKey 类型、TTL、值预览、长度统计

二、界面设计

2.1 触发方式

方式一:连接树右键菜单(推荐)

  • 在连接树中,右键点击表/集合/Key节点
  • 显示上下文菜单,包含"查看结构"选项
  • 点击后在结果面板的"结构"Tab中展示

方式二:连接树节点操作按钮

  • 在表/集合/Key节点上悬停显示操作按钮
  • 点击"结构"图标按钮,在结果面板展示

方式三:双击节点

  • 双击表/集合/Key节点自动切换到"结构"Tab并加载结构信息

推荐实现方式一,用户体验最佳。


2.2 展示位置设计

在结果面板中展示

表结构信息展示在现有的 ResultPanel 组件中,作为第三个 Tab

┌─────────────────────────────────────────────────────────┐
│  结果面板                                              │
├─────────────────────────────────────────────────────────┤
│  [结果] [消息] [结构]                                   │
├─────────────────────────────────────────────────────────┤
│  [查看模式] [编辑模式]  [刷新] [导出]                    │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  [结构 Tab 内容区域]                                    │
│  ┌─────────┬─────────┬─────────┐                      │
│  │ 字段信息 │ 索引信息 │ 其他信息 │                      │
│  └─────────┴─────────┴─────────┘                      │
│                                                         │
│                                                         │
└─────────────────────────────────────────────────────────┘

模式切换

  • 查看模式(默认):只读展示,显示表结构信息
  • 编辑模式:可编辑模式,支持修改字段、添加/删除索引等操作
  • 切换方式:通过模式切换按钮或 Tab 切换

展示区域属性

  • 位置:结果面板(ResultPanel)的第三个 Tab
  • Tab 标题:根据数据库类型显示
    • MySQL: 结构 - ${database}.${table}
    • MongoDB: 结构 - ${database}.${collection}
    • Redis: 结构 - ${key}
  • 高度:跟随结果面板高度(可调整,默认 300px
  • 滚动:内容超出时自动滚动

优势

  • 无需弹出窗口,界面更简洁
  • 与查询结果、消息在同一区域,操作连贯
  • 可以同时查看结构信息和查询结果
  • 符合现有架构,无需新增组件

2.3 内容展示设计

MySQL 表结构

Tab 1: 字段信息

┌─────────────────────────────────────────────────────────────┐
│ 字段名    │ 类型        │ 是否NULL │ 键  │ 默认值 │ 额外信息 │
├─────────────────────────────────────────────────────────────┤
│ id        │ int(11)     │ NO       │ PRI │ NULL   │ auto_inc │
│ name      │ varchar(50) │ YES      │     │ NULL   │          │
│ email     │ varchar(100)│ NO       │ UNI │ NULL   │          │
│ created_at│ datetime    │ NO       │     │ NULL   │          │
└─────────────────────────────────────────────────────────────┘

字段说明

  • 字段名:列名
  • 类型数据类型int, varchar, text, datetime 等)
  • 是否NULLYES/NO
  • PRI主键、UNI唯一键、MUL多键
  • 默认值:默认值或 NULL
  • 额外信息auto_increment、on update 等

Tab 2: 索引信息

┌─────────────────────────────────────────────────────────────┐
│ 索引名      │ 唯一 │ 字段        │ 排序 │ 索引类型          │
├─────────────────────────────────────────────────────────────┤
│ PRIMARY    │ 是   │ id          │ ASC  │ BTREE             │
│ idx_email  │ 是   │ email       │ ASC  │ BTREE             │
│ idx_name   │ 否   │ name        │ ASC  │ BTREE             │
└─────────────────────────────────────────────────────────────┘

字段说明

  • 索引名:索引名称
  • 唯一:是/否
  • 字段:索引字段(可能有多个,用逗号分隔)
  • 排序ASC/DESC
  • 索引类型BTREE、HASH 等

MongoDB 集合结构

Tab 1: 文档示例

┌─────────────────────────────────────────────────────────────┐
│ 文档 1                                                       │
├─────────────────────────────────────────────────────────────┤
│ {                                                            │
│   "_id": ObjectId("..."),                                   │
│   "name": "John",                                           │
│   "email": "john@example.com",                              │
│   "age": 30,                                                │
│   "created_at": ISODate("2025-01-01T00:00:00Z")            │
│ }                                                            │
└─────────────────────────────────────────────────────────────┘
[显示最多 5 个文档示例JSON 格式,可折叠展开]

Tab 2: 字段统计

┌─────────────────────────────────────────────────────────────┐
│ 字段名      │ 出现次数 │ 占比                                │
├─────────────────────────────────────────────────────────────┤
│ _id         │ 5        │ 100% (基于5个文档示例)            │
│ name        │ 5        │ 100%                                │
│ email       │ 4        │ 80%                                 │
│ age         │ 3        │ 60%                                 │
│ created_at  │ 2        │ 40%                                 │
└─────────────────────────────────────────────────────────────┘

文档总数: 1000
⚠️ 字段统计基于文档示例最多5个仅供参考

性能分析与优化建议

当前实现分析

  1. 字段统计(当前实现):

    • 查询方式基于文档示例最多5个进行统计
    • 性能影响 - 只查询5个文档几乎无性能影响
    • 准确性⚠️ 不准确 - 仅基于5个文档不能代表全表字段分布
    • 适用场景:快速预览,了解集合可能包含的字段
  2. 文档总数(当前实现):

    • 查询方式CountDocuments({}) - 全表扫描
    • 性能影响⚠️ 中等 - 大数据集(百万级+)可能较慢
    • 优化建议:使用 estimatedDocumentCount() 获取估算值(更快)

优化方案

方案一:保持当前实现(推荐)

  • 优点:性能好,响应快
  • ⚠️ 缺点:字段统计不准确
  • 适用:快速预览场景,不需要精确统计

方案二:采样统计(已确定采用) 默认采样 10个文档

  • 使用 $sample 聚合管道随机采样10个文档进行统计
  • 性能影响 - 采样10个文档性能良好
  • 准确性 适中 - 比5个文档更准确比全表扫描性能更好
  • 实现方式:使用 MongoDB $sample 聚合管道(已实现)
  • 异步加载 全异步执行,不阻塞主流程
  • 前端展示 显示"基于10个文档采样统计仅供参考"
  • 未来扩展支持可配置采样数量P2

方案三:全表统计(不推荐)

  • 扫描所有文档统计字段
  • 性能影响 - 大数据集可能非常慢
  • 适用:小数据集(< 10万文档

推荐实现

// 方案一:保持当前实现(快速预览)
// 字段统计基于文档示例5个性能好但准确性低
fieldStats := make(map[string]int)
for _, doc := range sampleDocs {  // 5个文档
    for key := range doc {
        fieldStats[key]++
    }
}

// 方案二:采样统计(可选,通过参数控制)
// 如果用户需要更准确的统计,可以采样更多文档
if needAccurateStats {
    pipeline := []bson.M{
        {"$sample": bson.M{"size": 1000}},  // 采样1000个文档
        {"$project": bson.M{"keys": bson.M{"$objectToArray": "$$ROOT"}}},
        {"$unwind": "$keys"},
        {"$group": bson.M{
            "_id": "$keys.k",
            "count": bson.M{"$sum": 1},
        }},
    }
    // 执行聚合查询...
}

前端展示建议

  1. 明确标注:字段统计显示"基于X个文档示例仅供参考"
  2. 可选刷新:提供"精确统计"按钮,用户需要时再执行采样统计
  3. 性能提示:大数据集时提示"精确统计可能较慢"
  4. 缓存策略字段统计结果缓存5-10分钟避免重复查询

最终建议(已确定)

  • 默认实现 使用采样统计默认采样10个文档性能好准确性适中
  • 文档总数 使用 estimatedDocumentCount() 替代 CountDocuments() 提升性能
  • 前端展示:明确标注"基于10个文档采样统计仅供参考"
  • 后续优化:可考虑提供"精确统计"按钮采样更多文档100-1000个作为P2功能

Tab 3: 索引信息

┌─────────────────────────────────────────────────────────────┐
│ 索引名      │ 唯一 │ 键定义                                  │
├─────────────────────────────────────────────────────────────┤
│ _id_        │ 是   │ {"_id": 1}                            │
│ idx_email   │ 是   │ {"email": 1}                          │
│ idx_name    │ 否   │ {"name": 1, "age": -1}               │
└─────────────────────────────────────────────────────────────┘

Redis Key 信息

单页展示(无 Tab

┌─────────────────────────────────────────────────────────────┐
│ Key 信息                                                     │
├─────────────────────────────────────────────────────────────┤
│ Key 名称: user:1001                                         │
│ Key 类型: hash                                              │
│ TTL: 3600 秒 (1 小时)                                        │
│ 长度: 5 个字段                                              │
├─────────────────────────────────────────────────────────────┤
│ 值预览:                                                      │
│ {                                                            │
│   "name": "John",                                           │
│   "email": "john@example.com",                              │
│   "age": "30"                                               │
│ }                                                            │
└─────────────────────────────────────────────────────────────┘

字段说明

  • Key 名称:完整的 Key 名称
  • Key 类型string、hash、list、set、zset 等
  • TTL:过期时间(秒),-1 表示永不过期,-2 表示 Key 不存在
  • 长度根据类型显示string=字符数hash/list/set/zset=元素数)
  • 值预览:限制显示前 200 字符,过长时显示省略号

三、组件设计

3.1 组件结构

ResultPanel.vue (现有组件,扩展)
└── 新增 "结构" Tab
    ├── StructureContent.vue (结构内容组件)
    │   ├── 模式切换(查看/编辑)
    │   ├── MySQLStructure.vue (MySQL 专用)
    │   │   ├── ViewMode.vue (查看模式)
    │   │   │   ├── FieldsTab.vue (字段信息子Tab)
    │   │   │   └── IndexesTab.vue (索引信息子Tab)
    │   │   └── EditMode.vue (编辑模式)
    │   │       ├── FieldsEditor.vue (字段编辑表格)
    │   │       ├── IndexesEditor.vue (索引编辑表格)
    │   │       └── EditToolbar.vue (保存/取消按钮)
    │   ├── MongoStructure.vue (MongoDB 专用)
    │   │   ├── ViewMode.vue (查看模式)
    │   │   │   ├── SampleDocsTab.vue (文档示例子Tab)
    │   │   │   ├── FieldStatsTab.vue (字段统计子Tab)
    │   │   │   └── IndexesTab.vue (索引信息子Tab)
    │   │   └── EditMode.vue (编辑模式)
    │   │       └── IndexesEditor.vue (索引编辑MongoDB不支持字段编辑)
    │   └── RedisStructure.vue (Redis 专用,仅查看模式)
    └── 状态管理(通过 composable

3.2 组件接口

ResultPanel.vue Props扩展

interface Props {
  // ... 现有 props
  structureData?: {
    connectionId: number
    database: string
    tableName: string
    dbType: 'mysql' | 'mongo' | 'redis'
  } | null  // 表结构数据null 表示不显示结构Tab
}

新增 Composable: useStructureState.ts

export function useStructureState() {
  const structureLoading = ref(false)
  const structureError = ref('')
  const structureData = ref<any>(null)
  const structureInfo = ref<{
    connectionId: number
    database: string
    tableName: string
    dbType: 'mysql' | 'mongo' | 'redis'
  } | null>(null)
  
  // 编辑模式相关
  const editMode = ref<'view' | 'edit'>('view')
  const editData = ref<any>(null)  // 编辑中的数据(用于撤销)
  const hasChanges = ref(false)    // 是否有未保存的修改

  const loadStructure = async (connectionId, database, tableName, dbType) => {
    // 加载表结构数据
  }

  const clearStructure = () => {
    structureData.value = null
    structureInfo.value = null
    editMode.value = 'view'
    editData.value = null
    hasChanges.value = false
  }

  const switchToEditMode = () => {
    // 切换到编辑模式,复制数据到 editData
    editData.value = JSON.parse(JSON.stringify(structureData.value))
    editMode.value = 'edit'
    hasChanges.value = false
  }

  const switchToViewMode = () => {
    // 切换到查看模式
    editMode.value = 'view'
    editData.value = null
    hasChanges.value = false
  }

  const saveStructure = async () => {
    // 保存结构修改,生成 ALTER TABLE 语句并执行
  }

  return {
    structureLoading,
    structureError,
    structureData,
    structureInfo,
    editMode,
    editData,
    hasChanges,
    loadStructure,
    clearStructure,
    switchToEditMode,
    switchToViewMode,
    saveStructure
  }
}

四、数据流程

4.1 数据获取流程

用户触发查看结构(右键菜单/操作按钮)
    ↓
ConnectionTree 触发 'table-structure' 事件
    ↓
index.vue 接收事件,调用 useStructureState.loadStructure()
    ↓
根据 connectionId 获取连接信息(确定 dbType
    ↓
调用 GetTableStructure API
    ↓
后端根据 dbType 分发:
  - MySQL → GetTableStructure (DESCRIBE 查询)
  - MongoDB → GetCollectionStructure (文档分析)
  - Redis → GetKeyInfo (命令查询)
    ↓
返回结构数据
    ↓
更新 structureData 和 structureInfo
    ↓
ResultPanel 检测到 structureInfo 不为空,显示"结构"Tab
    ↓
StructureContent 根据 dbType 渲染对应组件

4.2 API 调用

// 获取表结构
const result = await window.go.main.App.GetTableStructure(
  connectionId,
  database,
  tableName
)

// 返回数据结构
// MySQL:
{
  type: 'mysql',
  database: 'test',
  table: 'users',
  columns: [...],  // 字段信息数组
}

// MongoDB:
{
  type: 'mongo',
  database: 'test',
  collection: 'users',
  structure: {
    sampleDocs: [...],      // 文档示例
    fieldStats: {...},      // 字段统计
    indexes: [...],         // 索引信息
    documentCount: 1000      // 文档总数
  }
}

// Redis:
{
  type: 'redis',
  key: 'user:1001',
  info: {
    type: 'hash',
    ttl: 3600,
    length: 5,
    value: {...}            // 值预览
  }
}

五、实现细节

5.1 表格展示

使用 Arco Design Table 组件

  • 分页:字段/索引较多时,使用分页(每页 20 条)
  • 排序:支持按字段名、类型等排序
  • 搜索:字段信息表格支持搜索字段名
  • 固定列:字段名列固定,方便横向滚动查看

样式优化

  • 字体:使用等宽字体显示类型信息
  • 颜色主键字段用特殊颜色标识NULL 字段用灰色
  • 宽度:列宽自适应,最小宽度 100px

5.2 JSON 展示

MongoDB 文档示例、Redis 值预览

  • 使用 <pre> 标签展示格式化的 JSON
  • 支持折叠/展开(使用 a-collapse 组件)
  • 长文本自动换行,限制最大高度,超出部分滚动
  • 支持复制功能(点击复制按钮)

5.3 加载状态

  • 加载中:显示 Spin 组件和"加载中..."提示
  • 加载失败:显示错误提示,提供重试按钮
  • 空数据:显示空状态提示

5.4 响应式设计

  • 小屏幕:对话框宽度自适应,最小 600px
  • 表格:横向滚动,固定关键列
  • Tab内容过多时Tab 可滚动

六、交互设计

6.1 触发查看结构

  1. 从连接树触发

    • 右键菜单 → "查看结构"
    • 或点击节点操作按钮
    • 或双击节点
  2. 参数传递

    • 从节点数据获取 connectionIddatabasetableNamedbType
    • 通过事件传递给 index.vue
    • index.vue 调用 useStructureState.loadStructure()
  3. Tab 切换

    • 自动切换到结果面板的"结构"Tab
    • 如果结果面板隐藏,自动显示

6.2 结构Tab操作

  • 切换Tab:点击"结构"Tab查看点击其他Tab返回
  • 刷新在结构Tab中添加刷新按钮重新加载结构数据
  • 复制:字段信息、索引信息支持复制(选中文本或复制按钮)
  • 关闭切换到其他Tab或清空结构数据

6.3 数据更新

  • 自动加载:触发查看结构时自动加载数据
  • 手动刷新在结构Tab中提供刷新按钮
  • 错误重试:加载失败时显示错误提示和重试按钮
  • 清空数据切换连接或执行SQL时自动清空结构数据

七、技术实现要点

7.1 组件拆分

  • 扩展组件ResultPanel.vue 添加"结构"Tab
  • 内容组件StructureContent.vue 负责根据 dbType 路由到对应组件
  • 专用组件MySQLStructure.vueMongoStructure.vueRedisStructure.vue
  • 复用组件IndexesTab.vue 可被 MySQL 和 MongoDB 复用(需适配数据格式)
  • 状态管理useStructureState.ts composable 管理结构数据状态

7.2 数据格式化

  • MySQL 字段类型:保持原样显示(如 int(11)varchar(50)
  • MongoDB 文档BSON 转换为 JSON 格式显示
  • Redis 值根据类型格式化string 直接显示hash 显示为对象)

7.3 性能优化

  • 懒加载结构Tab切换时才加载对应内容使用 v-if
  • 数据缓存:同一表结构数据缓存 5 分钟,避免重复请求
  • 分页加载:字段/索引较多时使用分页,避免一次性加载过多数据
  • 按需渲染:只有在 structureInfo 不为空时才渲染结构Tab

八、扩展功能(可选)

8.1 导出功能

  • 导出为 SQLMySQL 表结构导出为 CREATE TABLE 语句
  • 导出为 JSONMongoDB 集合结构导出为 JSON Schema
  • 导出为文本:所有类型支持导出为文本格式

8.2 编辑功能(融入查看区域)

设计原则

  • 融入查看区域:编辑功能直接在结构查看 Tab 中实现,通过模式切换
  • 统一界面:查看和编辑使用相同的布局和组件,减少界面切换
  • 权限检查编辑前检查用户权限ALTER TABLE、CREATE INDEX 等)
  • 操作确认:结构修改是危险操作,需要确认对话框

编辑模式设计

模式切换

┌─────────────────────────────────────────────────────────┐
│  结构 - database.table                    [查看] [编辑] │
├─────────────────────────────────────────────────────────┤
│  [字段信息] [索引信息]                                   │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  [编辑模式内容]                                          │
│  - 可编辑表格(字段信息)                                │
│  - 添加字段按钮                                         │
│  - 删除字段按钮                                         │
│  - 保存/取消按钮                                         │
│                                                         │
└─────────────────────────────────────────────────────────┘

编辑功能

  • MySQL
    • 修改字段类型、是否NULL、默认值、注释
    • 添加字段:在指定位置添加新字段
    • 删除字段:删除不需要的字段(需确认)
    • 修改索引:添加/删除索引
  • MongoDB
    • 添加索引:创建新索引
    • 删除索引:删除不需要的索引(需确认)
    • 注意MongoDB 字段是动态的,不支持字段编辑
  • Redis
    • 不支持编辑Redis 是键值存储,无结构概念)

实现方式

方式一Tab 切换(推荐)

  • 在结构 Tab 内部使用子 Tab 切换查看/编辑模式
  • 查看 Tab只读展示
  • 编辑 Tab可编辑表格带保存/取消按钮

方式二:按钮切换

  • 在结构 Tab 顶部添加"编辑"按钮
  • 点击后切换到编辑模式,按钮变为"查看"
  • 编辑模式下显示保存/取消按钮

推荐使用方式一,界面更清晰,模式切换更明显。

编辑操作流程

用户点击"编辑"Tab/按钮
    ↓
检查权限ALTER TABLE、CREATE INDEX
    ↓
加载当前结构数据到编辑表格
    ↓
用户修改字段/索引
    ↓
点击"保存"按钮
    ↓
生成 ALTER TABLE 语句
    ↓
显示确认对话框(显示将要执行的 SQL
    ↓
用户确认
    ↓
执行 ALTER TABLE 语句
    ↓
刷新结构数据
    ↓
切换回查看模式

安全措施

  1. 权限检查:编辑前检查数据库用户权限
  2. 确认对话框:显示将要执行的 SQL用户必须确认
  3. 操作日志:记录所有结构修改操作
  4. 撤销功能支持撤销最近一次修改可选P2
  5. 备份提示重要表修改前提示备份可选P2

8.3 对比功能

  • 结构对比:对比两个表的结构差异
  • 版本历史:记录表结构变更历史(需要额外存储)

九、实现优先级

P0必须实现

  1. 在 ResultPanel 中添加"结构"Tab
  2. useStructureState composable 实现
  3. MySQL 字段信息展示
  4. MySQL 索引信息展示
  5. MongoDB 文档示例展示
  6. MongoDB 字段统计展示
  7. Redis Key 信息展示
  8. 连接树右键菜单触发

P0.5(查看功能完成后实现)

  1. 查看/编辑模式切换
  2. MySQL 字段编辑修改类型、NULL、默认值
  3. MySQL 索引编辑(添加/删除索引)
  4. MongoDB 索引编辑(添加/删除索引)
  5. 权限检查
  6. 确认对话框

P1重要功能

  1. 数据加载状态和错误处理
  2. JSON 格式化显示
  3. 表格搜索和排序
  4. 自动切换到结构Tab
  5. 清空结构数据逻辑切换连接、执行SQL时

P2优化功能

  1. 数据缓存
  2. 复制功能
  3. 导出功能
  4. 响应式优化
  5. 编辑模式撤销/重做
  6. 修改前备份提示

十、总结

表结构查看功能设计遵循以下原则:

  1. 统一接口:不同数据库类型使用相同的触发方式和展示框架
  2. 差异化展示:根据数据库类型展示对应的结构信息
  3. 集成设计:在结果面板中展示,无需弹出窗口,界面更简洁
  4. 用户体验提供清晰的表格展示、JSON 格式化、搜索排序等功能
  5. 性能优化:懒加载、数据缓存、分页等优化措施
  6. 可扩展性:组件化设计,便于后续添加新功能

设计优势

  • 无需弹出窗口:在结果面板中展示,界面更简洁
  • 操作连贯:与查询结果、消息在同一区域,切换方便
  • 符合现有架构:扩展 ResultPanel 组件,无需新增复杂组件
  • 状态管理清晰:使用 composable 管理结构数据,易于维护
  • 查看编辑融合:编辑功能融入查看区域,通过模式切换,无需额外界面
  • 统一体验:查看和编辑使用相同布局,降低学习成本

编辑功能融入优势

  • 无缝切换:查看和编辑在同一区域,切换流畅
  • 上下文保持:编辑时可以看到原始结构,便于对比
  • 操作连贯:查看 → 编辑 → 保存 → 查看,流程顺畅
  • 界面简洁:不需要额外的编辑窗口或页面

通过以上设计,可以实现一个功能完善、用户体验良好的表结构查看和编辑功能。