Private
Public Access
1
0
Files
u-desk/docs/04-功能迭代/GO-DESK-2.数据库客户端/设计文档/需求设计/前端布局样式系统设计.md
绝尘 a5d30684ed 重构:文件系统模块化架构,增强 Markdown 渲染
- 拆分 FileSystem.vue 为模块化组件架构
- 新增 Markdown Mermaid 图表渲染支持
- 新增 180+ 编程语言代码高亮
- 修复编辑/预览模式切换渲染问题
- 优化亮色/暗色模式主题适配
- 新增 TypeScript 类型定义
2026-02-04 03:32:46 +08:00

39 KiB
Raw Blame History

前端布局样式系统设计

创建日期2026-01-01
最后更新2026-01-09
目标:建立系统化的前端布局和样式规范,确保一致性和可维护性
原则:统一规范、可扩展、易维护、主题兼容
状态 已完成 Arco Design 规范优化


📋 快速导航



一、设计目标

核心目标

  • 一致性:统一的布局和样式规范
  • 可维护性:清晰的样式组织结构
  • 可扩展性:支持主题切换、响应式布局、功能扩展
  • 性能:优化样式性能,减少重复代码

设计原则

  • 使用 Arco Design 基础样式(优先使用样式变量)
  • 避免硬编码样式(使用 CSS 变量和设计令牌)
  • 组件化样式(每个组件管理自己的样式)
  • 响应式优先(支持不同屏幕尺寸)

二、布局系统

2.1 Arco Design Layout 组件使用规范

2.1.1 Arco Layout 组件结构

Arco Design 提供了以下 Layout 组件:

  • a-layout: 布局容器
  • a-layout-header: 顶部导航栏
  • a-layout-sider: 侧边栏
  • a-layout-content: 内容区域
  • a-layout-footer: 底部栏

2.1.2 我们的实现方式

顶层布局App.vue - 符合 Arco 规范

<a-layout class="layout">
  <a-layout-header>顶部导航</a-layout-header>
  <a-layout-content>内容区域</a-layout-content>
</a-layout>

数据库客户端布局db-cli/index.vue - 已优化为使用 Arco Layout 组件

<a-layout class="db-cli-layout">
  <a-layout-sider :width="280">侧边栏</a-layout-sider>
  <a-layout class="main-layout">  <!--  使用嵌套 a-layout -->
    <a-layout-content class="editor-area">编辑器</a-layout-content>
    <a-layout-content class="result-area">结果</a-layout-content>
  </a-layout>
</a-layout>

优化说明

  • 使用嵌套的 a-layout 替代自定义 div.main-content
  • 使用 a-layout-content 作为编辑器和结果区域
  • 完全符合 Arco Design 规范
  • 保持了原有的灵活性和功能(拖拽调整、百分比高度等)

2.2 整体布局结构

┌─────────────────────────────────────────────────────────┐
│            db-cli-layout (Arco Layout, 100vh)           │
│  ┌──────────────┐  ┌─────────────────────────────────┐ │
│  │   sidebar    │  │      main-content (flex:1)      │ │
│  │  (280px)     │  │  ┌───────────────────────────┐ │ │
│  │              │  │  │   editor-area             │ │ │
│  │ sidebar-     │  │  │   (height: %, 可隐藏)     │ │ │
│  │ container    │  │  │   └─ SqlEditor            │ │ │
│  │              │  │  └───────────────────────────┘ │ │
│  │ Connection-  │  │  ┌───────────────────────────┐ │ │
│  │ Tree         │  │  │ editor-result-divider (4px)│ │ │
│  └──────────────┘  │  └───────────────────────────┘ │ │
│                    │  ┌───────────────────────────┐ │ │
│                    │  │   result-area (flex:1)    │ │ │
│                    │  │   └─ ResultPanel          │ │ │
│                    │  │       └─ Tabs             │ │ │
│                    │  │           ├─ result       │ │ │
│                    │  │           ├─ messages     │ │ │
│                    │  │           ├─ structure    │ │ │
│                    │  │           ├─ history      │ │ │
│                    │  │           └─ create       │ │ │
│                    │  └───────────────────────────┘ │ │
│                    └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

2.3 布局层次

层级 元素 Arco 组件 类型 说明
顶层App.vue
0 layout a-layout Arco Layout 应用主容器100vh垂直 Flex
0.1 header a-layout-header Arco Header 顶部导航栏(固定高度)
0.2 content a-layout-content Arco Content 主内容区域flex:1可滚动
数据库客户端db-cli/index.vue
1 db-cli-layout a-layout Arco Layout 数据库客户端容器100%,水平 Flex
2 sidebar a-layout-sider Arco Sider 侧边栏280pxflex-shrink: 0
2.1 sidebar-container - 自定义 div 侧边栏容器100%高度Flex 列)
3 main-layout a-layout Arco Layout 主布局容器flex:1垂直 Flex 已优化
4 editor-area a-layout-content Arco Content 编辑器区域(百分比高度,可隐藏) 已优化
4.1 editor-result-divider - 自定义 div 分隔条4px可调整大小
5 result-area a-layout-content Arco Content 结果区域flex:1min-height: 150px 已优化
5.1 result-panel-wrapper - 自定义 div 结果面板容器Flex 列)
5.2 result-tabs a-tabs Arco Tabs Tabs 容器flex:1
5.3 tab-content - 自定义 div 各 Tab 内容区域height:100%

Arco 组件使用情况(已优化):

  • 使用了 a-layout 作为容器
  • 使用了 a-layout-sider 作为侧边栏
  • 使用嵌套 a-layout 作为主内容区容器 已优化
  • 使用 a-layout-content 作为编辑器和结果区域 已优化
  • 使用了 a-tabs 作为结果面板的标签页

2.4 Arco Layout 组件的样式特性

2.4.1 Arco Layout 默认样式

Arco Design 的 Layout 组件具有以下默认样式特性:

/* a-layout */
.arco-layout {
  display: flex;
  flex: auto;
  flex-direction: column;
  box-sizing: border-box;
}

/* a-layout-header / a-layout-footer */
.arco-layout-header,
.arco-layout-footer {
  flex: 0 0 auto;
}

/* a-layout-sider */
.arco-layout-sider {
  position: relative;
  min-width: 0;
  transition: all 0.2s;
}

/* a-layout-content */
.arco-layout-content {
  flex: auto;
}

2.4.2 我们的样式覆盖

我们为 db-cli-layout 覆盖了部分样式,使其适配水平布局:

.db-cli-layout {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: row;  /* 覆盖默认的 column改为水平布局 */
  overflow: hidden;
}

.sidebar {
  flex-shrink: 0;
  width: 280px;
  /* Arco 的 a-layout-sider 会应用默认样式,我们通过 class 覆盖特定样式 */
}

注意事项

  • a-layout 默认是垂直 Flexflex-direction: column),我们在 .db-cli-layout 中覆盖为水平(row
  • a-layout-sider 的宽度通过 :width="280" prop 设置,符合 Arco 规范
  • 已优化:使用嵌套 a-layouta-layout-content 替代自定义 div.main-content
  • 已优化:所有样式使用 Arco 设计令牌,简化写法

2.5 布局样式规范

主布局容器

.db-cli-layout {
  width: 100%;
  height: 100%;
  display: flex;
  overflow: hidden;
}

.sidebar {
  flex-shrink: 0;
  width: 280px;
  border-right: 1px solid var(--color-border-2);  /* ✅ 已优化:简化边框写法 */
  overflow: hidden;
}

.sidebar-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 主布局容器 - 使用 Arco Layout */
.main-layout {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}

编辑器区域 - 使用 Arco Layout Content

.editor-area {
  flex-shrink: 0;
  min-height: 150px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  padding: 0;  /* 移除 Arco Layout Content 的默认 padding */
  /* 高度通过 :style="{ height: editorAreaHeight + '%' }" 动态设置 */
}

.editor-result-divider {
  flex-shrink: 0;
  height: 4px;
  background: var(--color-border-2);
  cursor: row-resize;
  position: relative;
  transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);  /* 使用 Arco 过渡函数 */
  display: flex;
  align-items: center;
  justify-content: center;
}

.editor-result-divider:hover {
  background: var(--color-border-3);
}

.editor-result-divider.collapsed {
  cursor: pointer;
  height: 6px;
}

分隔条按钮 - 使用 Arco 设计令牌

.divider-toggle-btn {
  position: absolute;
  z-index: 10;
  background: var(--color-bg-1);
  border: 1px solid var(--color-border-2);
  border-radius: var(--border-radius-small, 2px);  /* 使用 Arco 圆角变量 */
  box-shadow: var(--shadow-1-down, 0 2px 4px rgba(0, 0, 0, 0.06));  /* 使用 Arco 阴影变量 */
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  padding: 0;
  min-width: 30px;
  height: 15px;
}

.divider-toggle-btn:hover {
  background: var(--color-bg-2);
  border-color: var(--color-primary-light-2);
  box-shadow: var(--shadow-2-down, 0 4px 8px rgba(0, 0, 0, 0.1));
  transform: translateY(-1px);
}

结果区域 - 使用 Arco Layout Content

.result-area {
  flex: 1;
  min-height: 150px;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--color-border-2);  /* 简化边框样式 */
  overflow: hidden;
  position: relative;
  height: 100%;
  padding: 0;  /* 移除 Arco Layout Content 的默认 padding */
}

.result-panel-wrapper {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
}

2.6 Arco Tabs 组件使用规范

2.6.1 Arco Tabs 组件结构

Arco Design 的 Tabs 组件结构:

arco-tabs
├── arco-tabs-header (标签头部flex-shrink: 0)
│   └── arco-tabs-nav
│       └── arco-tabs-tab (各个标签页)
└── arco-tabs-content (标签内容区域flex: 1)
    └── arco-tabs-content-list
        └── arco-tabs-content-item (各个内容项)

2.6.2 我们的实现方式

<a-tabs 
  v-model:active-key="resultTab" 
  type="line"
  class="result-tabs"
>
  <a-tab-pane key="result" title="结果">...</a-tab-pane>
  <a-tab-pane key="messages" title="消息">...</a-tab-pane>
  <!-- ... -->
</a-tabs>

使用规范核对

  • 使用 v-model:active-key 控制激活标签 - 符合 Arco 规范
  • 使用 type="line" 设置标签样式 - 符合 Arco 规范
  • 使用 a-tab-pane 定义各个标签页 - 符合 Arco 规范
  • 使用 keytitle 属性 - 符合 Arco 规范

2.6.3 Tabs 内容区域布局

Arco Tabs 深度样式设置

Arco Tabs 默认样式特性

  • arco-tabs: 默认 display: flex; flex-direction: column
  • arco-tabs-header: 默认 flex-shrink: 0(固定高度)
  • arco-tabs-content: 默认 flex: 1(占据剩余空间)

我们的样式覆盖(确保高度计算正确):

.result-tabs {
  flex: 1;
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 确保 arco-tabs 容器高度正确 */
.result-tabs :deep(.arco-tabs) {
  height: 100%;              /* ✅ 关键:设置高度为 100% */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 内容区域占据剩余空间 */
.result-tabs :deep(.arco-tabs-content) {
  flex: 1;                   /* ✅ 符合 Arco 默认样式 */
  min-height: 0;             /* ✅ 关键:允许收缩 */
  overflow: hidden;
}

/* 内容列表高度设置 */
.result-tabs :deep(.arco-tabs-content-list) {
  height: 100%;              /* ✅ 关键:确保列表高度正确 */
}

/* 各个内容项高度设置 */
.result-tabs :deep(.arco-tabs-content-item) {
  height: 100%;              /* ✅ 关键:每个内容项高度 100% */
  display: flex;             /* ✅ 添加 Flex 布局支持 */
  flex-direction: column;
  overflow: hidden;
}

关键点

  1. arco-tabs-content 使用 flex: 1 - 符合 Arco 默认样式
  2. arco-tabs-content-item 使用 height: 100% - 确保内容项高度正确
  3. 添加 min-height: 0 - 允许 Flex 子元素正确收缩
  4. 使用 :deep() 深度选择器覆盖 Arco 内部样式 - Vue 3 标准做法

Tab Content 通用样式

所有 Tab 内容都遵循相同的布局模式:

.tab-content {
  height: 100%;           /* 使用 height: 100% 而非 flex: 1 */
  display: flex;
  flex-direction: column;
  padding: var(--spacing-md, 12px);
  overflow: hidden;
  min-height: 0;
}

具体 Tab 内容结构

结果 Tab (result-content)

result-content (height: 100%)
├── result-loading / result-empty (flex: 1, 居中)
└── result-data-wrapper (flex: 1, overflow: hidden)
    ├── result-stats (flex-shrink: 0)
    └── result-table-container / result-json-container (flex: 1)

消息 Tab (messages-content)

messages-content (height: 100%)
└── messages-list (flex: 1, overflow-y: auto)
    ├── message-item (列表项)
    └── messages-empty (flex: 1, 居中)

结构 Tab (structure-content)

structure-content (height: 100%)
└── structure-data (flex: 1, overflow-y: auto)
    └── structure-section
        ├── structure-section-header (flex-shrink: 0)
        └── structure-table-container (flex: 1)

历史 Tab (history-content)

history-content (height: 100%)
├── history-toolbar (flex-shrink: 0)
├── history-loading / history-empty (flex: 1, 居中)
└── history-timeline-wrapper (flex: 1, overflow: hidden)
    ├── history-timeline (flex: 1, overflow-y: auto)
    └── history-pagination-wrapper (flex-shrink: 0)

创建 Tab (create-content)

create-content (height: 100%)
└── create-content > div (flex: 1)
    ├── MySQLCreate / 其他组件
    └── create-actions (flex-shrink: 0)

三、样式系统

3.1 设计令牌Design Tokens- Arco Design 标准

间距系统 已统一使用

/* Arco Design 间距变量(优先使用) */
--spacing-xs: 4px;   
--spacing-sm: 8px;   
--spacing-md: 12px;
--spacing-lg: 16px;  
--spacing-xl: 20px;  
--spacing-xxl: 24px;

使用规范

  • 所有 padding 和 margin 都应使用这些变量
  • 避免硬编码数值(如 padding: 8pxpadding: var(--spacing-sm, 8px)

颜色系统 已统一使用

/* 边框颜色 */
--color-border-1, --color-border-2, --color-border-3, --color-border-4

/* 背景颜色 */
--color-bg-1, --color-bg-2, --color-bg-3, --color-bg-4

/* 文本颜色 */
--color-text-1, --color-text-2, --color-text-3, --color-text-4

/* 主题色 */
--color-primary, --color-primary-light-1  light-5

使用规范

  • 简化边框写法:1px solid var(--color-border-2)(已优化)
  • 避免使用 var(--color-border-2, var(--color-border)) 这种多层 fallback
  • 主题色使用 --color-primary-light-* 系列

字体系统 已统一使用

/* Arco Design 字体大小变量 */
--font-size-xs: 12px;  
--font-size-sm: 13px;  /* 注意:不是 14px */
--font-size-md: 14px;
--font-size-lg: 16px;

/* 字体族 */
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ...;
--font-family-mono: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;

使用规范

  • 所有文本大小使用这些变量
  • 代码/等宽字体使用 --font-family-mono

边框系统 已统一使用

/* 圆角 */
--border-radius-small: 2px;
--border-radius-medium: 4px;
--border-radius-large: 6px;

/* 边框 */
border: 1px solid var(--color-border-2);  /* ✅ 简化写法 */

使用规范

  • 使用 --border-radius-small, --border-radius-medium, --border-radius-large
  • 边框统一使用 1px solid var(--color-border-2) 简化写法

阴影系统 已统一使用

/* Arco Design 阴影变量 */
--shadow-1-down: 0 2px 4px rgba(0, 0, 0, 0.06);
--shadow-2-down: 0 4px 8px rgba(0, 0, 0, 0.1);
--shadow-3-down: 0 8px 16px rgba(0, 0, 0, 0.12);

使用规范

  • 使用 Arco 阴影变量替代硬编码 rgba()
  • hover 状态使用 --shadow-2-down,默认使用 --shadow-1-down

过渡函数 已统一使用

/* Arco Design 标准过渡函数 */
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);

/* 或者更精确地指定属性 */
transition: border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1), 
            box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);

使用规范

  • 所有过渡动画使用 cubic-bezier(0.4, 0, 0.2, 1)
  • 过渡时间统一使用 0.2s

3.2 Flex 布局规范

Flex 容器基础规范

.flex-container {
  display: flex;
  overflow: hidden;
  min-width: 0;      /* 关键:允许 flex 子元素收缩 */
  min-height: 0;     /* 关键:允许 flex 子元素收缩 */
}

高度计算关键点

1. Flex 容器中的高度计算

  • 使用 height: 100% 而非 flex: 1 作为子元素高度设置
  • 必须设置 min-height: 0 允许 flex 子元素正确收缩
  • 滚动容器应该使用 overflow-y: auto 而非 overflow: hidden

2. Arco Tabs 内容区域高度设置

/* Arco Tabs 内容项必须使用 height: 100% */
.arco-tabs-content-item {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Tab Content 使用 height: 100% 而非 flex: 1 */
.tab-content {
  height: 100%;        /* ✅ 正确 */
  /* flex: 1;         ❌ 错误,会导致高度计算不准确 */
}

3. 滚动容器的正确设置

/* 滚动容器应该设置在内容区域,而非外层容器 */
.scroll-container {
  flex: 1;
  overflow-y: auto;    /* 滚动设置在内容层 */
  overflow-x: hidden;
  min-height: 0;       /* 必须设置 */
}

/* 外层容器隐藏溢出 */
.outer-container {
  overflow: hidden;    /* 外层隐藏溢出 */
  min-height: 0;
}

3.3 组件样式规范BEM 命名)

.component-wrapper { }
.component-header { }
.component-content { }
.component-item--active { }
.component-item--disabled { }

样式组织顺序:容器样式 → 布局样式 → 功能样式 → 状态样式 → 深度选择器


四、响应式设计

4.1 断点定义

--breakpoint-xs: 480px;  --breakpoint-sm: 768px;  --breakpoint-md: 992px;
--breakpoint-lg: 1200px;  --breakpoint-xl: 1600px;

4.2 响应式策略

屏幕尺寸 策略
< 768px 侧边栏折叠/隐藏,编辑器/结果区域垂直堆叠
768px - 1200px 保持当前布局,适当调整比例
> 1200px 保持当前布局,可增加侧边栏宽度

五、主题支持

  • 优先使用 Arco Design 主题变量var(--color-*)var(--spacing-*)
  • 避免硬编码颜色:确保主题切换时样式正确
  • 测试主题兼容性:在明暗主题下测试样式

六、样式最佳实践

推荐做法

  1. 使用 Arco Design 变量:padding: var(--spacing-md); color: var(--color-text-1);
  2. 使用 Flex 布局:display: flex; flex-direction: column; overflow: hidden; min-height: 0;
  3. 使用 scoped 样式:<style scoped>
  4. 清晰的命名:.result-panel-wrapper { }

避免做法

  1. 硬编码数值:padding: 12px;padding: var(--spacing-md);
  2. 硬编码颜色:color: #333;color: var(--color-text-1);
  3. 过度嵌套:.wrapper .content .item .text.item-text
  4. 使用 !important避免使用优先提高选择器特异性

七、组件样式规范

7.1 ConnectionTree

connection-tree-wrapper
├── sidebar-header (flex-shrink: 0)
└── sidebar-content (flex: 1)

7.2 SqlEditor

sql-editor-wrapper (height: 100%)
├── editor-tabs (flex-shrink: 0)
├── editor-toolbar (flex-shrink: 0)
└── editor-container (flex: 1, overflow: hidden)
    └── Monaco Editor / CodeMirror

7.3 ResultPanel

result-panel-wrapper (height: 100%, flex 列)
└── result-tabs (flex: 1, height: 100%)
    └── Arco Tabs
        ├── arco-tabs-header (flex-shrink: 0)
        └── arco-tabs-content (flex: 1)
            └── arco-tabs-content-item (height: 100%)
                └── tab-content (height: 100%, flex 列)
                    └── 具体内容...

各 Tab Content 详细结构

结果 Tab

.result-content {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: var(--spacing-md, 12px);
  overflow: hidden;
  min-height: 0;
}

.result-data-wrapper {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.result-table-container {
  flex: 1;
  min-height: 0;
  /* 表格使用 scroll.y 属性控制滚动 */
}

消息 Tab

.messages-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: var(--spacing-md, 12px);
  overflow: hidden;
  min-height: 0;
}

.messages-list {
  flex: 1;
  overflow-y: auto;    /* 滚动设置在列表容器 */
  min-height: 0;
}

历史 Tab

.history-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 12px;
  overflow: hidden;
  min-height: 0;
}

.history-timeline-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
  position: relative;
}

.history-timeline {
  flex: 1;
  overflow-y: auto;    /* Timeline 容器滚动 */
  overflow-x: hidden;
  padding: 4px 4px 4px 0;
  min-height: 0;
}

.history-pagination-wrapper {
  flex-shrink: 0;      /* 分页器固定高度 */
  padding: 8px 0;
  border-top: 1px solid var(--color-border-2);
}

八、实际实现细节

8.1 编辑器区域高度控制

实现方式:百分比高度 + 可隐藏

// 编辑器高度使用百分比,存储在 localStorage
const editorAreaHeight = ref<number>(() => {
  const saved = localStorage.getItem('editor_area_height')
  return saved ? Number(saved) : 40  // 默认 40%
})

// 编辑器可隐藏/显示
const editorVisible = ref<boolean>(true)

// 动态设置高度
<div v-if="editorVisible" class="editor-area" :style="{ height: editorAreaHeight + '%' }">

分隔条调整功能

  • 分隔条高度4px展开时或 6px折叠时
  • 支持鼠标拖拽调整编辑器/结果区域比例
  • 调整时实时更新 editorAreaHeight 百分比
  • 调整结束后保存到 localStorage

8.2 Tab 内容高度计算要点

关键原则

  1. .arco-tabs-content-item 必须使用 height: 100%
  2. Tab Content 使用 height: 100% 而非 flex: 1
  3. 滚动容器设置在内容层,外层容器 overflow: hidden
  4. 所有 flex 容器必须设置 min-height: 0

常见问题与解决方案

问题Tab 内容不显示或高度不正确

/* 错误:使用 flex: 1 */
.tab-content {
  flex: 1;  /* ❌ 在 height: 100% 的父容器中会导致问题 */
}

解决:使用 height: 100%

/* 正确 */
.tab-content {
  height: 100%;  /* ✅ 与父容器高度一致 */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
}

问题:滚动条不出现或内容被挤压

/* 错误:在外层容器设置滚动 */
.outer-container {
  overflow-y: auto;  /* ❌ 滚动应该在内层内容容器 */
}

解决:在内容容器设置滚动

/* 正确 */
.outer-container {
  overflow: hidden;  /* ✅ 外层隐藏溢出 */
}

.content-scroll {
  flex: 1;
  overflow-y: auto;  /* ✅ 内容层滚动 */
  min-height: 0;
}

8.3 扩展性设计

8.3.1 布局配置接口

interface LayoutConfig {
  sidebar: {
    width: number              // 当前280px
    collapsible: boolean       // 当前:不支持
    collapsed: boolean         // 当前:不支持
    resizable: boolean         // 未来:可调整宽度
    minWidth: number           // 未来:最小宽度 200px
    maxWidth: number           // 未来:最大宽度 400px
  }
  mainContent: {
    editorHeight: number       // 当前:百分比(如 40%
    editorVisible: boolean     // 当前:支持显示/隐藏
    editorMinHeight: number    // 当前150px
    resultMinHeight: number    // 当前150px
    resizable: boolean         // 当前:支持拖拽调整
    resizeMode: 'percent'      // 当前:百分比模式
    // 未来扩展
    resizeMode?: 'pixel'       // 未来:像素模式
    editorRatio?: number       // 未来比例模式2:3
    resultRatio?: number
  }
  responsive: {
    sidebarBehavior?: 'hide' | 'collapse' | 'overlay'
    editorBehavior?: 'stack' | 'hide'
  }
}

8.3.2 当前实现状态

功能 状态 说明
编辑器/结果区域调整 已实现 使用百分比高度,支持拖拽调整
编辑器显示/隐藏 已实现 支持隐藏编辑器区域
侧边栏宽度调整 未实现 固定 280px
侧边栏折叠 未实现 暂不支持
响应式布局 未实现 暂不支持移动端适配
布局模式切换 未实现 暂不支持预设比例切换

8.4 区域大小调整实现

当前实现:编辑器/结果分隔条

HTML 结构

<!-- 编辑器/结果分隔条 -->
<div 
  v-if="editorVisible" 
  class="editor-result-divider" 
  @mousedown="handleEditorResultDividerMouseDown"
>
  <a-button type="text" size="mini" class="divider-toggle-btn" @click.stop="toggleEditor">
    <template #icon><icon-down/></template>
  </a-button>
</div>

<!-- 编辑器隐藏时的展开按钮 -->
<div v-if="!editorVisible" class="editor-result-divider collapsed">
  <a-button type="text" size="mini" class="divider-toggle-btn" @click="toggleEditor">
    <template #icon><icon-up/></template>
  </a-button>
</div>

样式实现

.editor-result-divider {
  flex-shrink: 0;
  height: 4px;
  background: var(--color-border-2);
  cursor: row-resize;              /* 调整光标 */
  position: relative;
  transition: background 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
}

.editor-result-divider:hover {
  background: var(--color-border-3);
}

.editor-result-divider.collapsed {
  cursor: pointer;
  height: 6px;
}

调整逻辑TypeScript

const handleEditorResultDividerMouseDown = (e: MouseEvent) => {
  e.preventDefault()
  
  const startY = e.clientY
  const startHeight = editorAreaHeight.value
  const containerHeight = mainContentRef.value?.clientHeight || 0
  
  const handleMouseMove = (moveEvent: MouseEvent) => {
    const deltaY = moveEvent.clientY - startY
    const deltaPercent = (deltaY / containerHeight) * 100
    const newHeight = Math.max(20, Math.min(80, startHeight + deltaPercent))
    editorAreaHeight.value = newHeight
  }
  
  const handleMouseUp = () => {
    document.removeEventListener('mousemove', handleMouseMove)
    document.removeEventListener('mouseup', handleMouseUp)
    localStorage.setItem('editor_area_height', editorAreaHeight.value.toString())
  }
  
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
}

8.5 滚动条处理

全局滚动条样式

系统使用统一的滚动条样式(定义在 web/src/style.css

/* Webkit浏览器 (Chrome, Safari, Edge) */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: transparent;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb {
  background: var(--color-border-2, rgba(0, 0, 0, 0.1));
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: padding-box;
  transition: background-color 0.2s ease;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--color-border-3, rgba(0, 0, 0, 0.2));
  background-clip: padding-box;
}

/* Firefox */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-2, rgba(0, 0, 0, 0.1)) transparent;
}

滚动容器设置原则

  1. 表格滚动:使用 Arco Table 的 scroll.y 属性,而非 CSS overflow-y
  2. 列表滚动:在内容容器设置 overflow-y: auto
  3. JSON/代码滚动:在 <pre> 容器设置 overflow: auto

8.6 未来扩展规划

布局模式切换(规划中)

enum LayoutMode {
  DEFAULT = 'default',      // 自定义比例(当前实现)
  BALANCED = 'balanced',    // 1:1 比例
  EDITOR_FOCUS = 'editor', // 编辑器占 70%
  RESULT_FOCUS = 'result', // 结果占 70%
  FULL_EDITOR = 'full-editor',
  FULL_RESULT = 'full-result'
}

区域插件化(规划中)

interface LayoutRegion {
  id: string
  name: string
  component: Component
  position: 'sidebar' | 'main' | 'top' | 'bottom'
  order: number
  visible: boolean
}

九、实施计划

第一阶段:规范制定

  • 创建布局样式系统设计文档
  • 定义设计令牌
  • 制定样式规范

第二阶段:基础布局实现

  • 实现主布局结构(侧边栏 + 主内容区)
  • 实现编辑器/结果区域分割
  • 实现编辑器显示/隐藏功能
  • 实现编辑器/结果区域拖拽调整

第三阶段Tab 内容布局优化

  • 修复 Arco Tabs 内容区域高度计算
  • 统一所有 Tab Content 的布局模式
  • 修复滚动条显示问题
  • 优化历史、消息、结构 Tab 的滚动处理

第四阶段:样式优化(进行中)

  • 统一使用 Arco Design 变量
  • 检查并替换剩余的硬编码值
  • 优化样式组织结构
  • 添加全局滚动条样式

第五阶段:扩展功能(规划中)

  • 实现侧边栏宽度调整
  • 实现侧边栏折叠功能
  • 实现响应式布局
  • 实现布局模式预设切换

十、检查清单

样式检查

  • 是否使用 Arco Design 变量?(大部分已实现)
  • 是否避免硬编码数值和颜色?(大部分已实现)
  • 是否使用 scoped 样式?(所有组件使用 scoped
  • 是否遵循命名规范?(使用 BEM 风格命名)

布局检查

  • 是否使用 Flex 布局?(所有容器使用 Flex
  • 是否设置 overflow: hidden?(外层容器已设置)
  • 是否设置 min-width: 0min-height: 0?(已设置)

Tab 内容高度检查

  • .arco-tabs-content-item 是否使用 height: 100%?(已设置)
  • Tab Content 是否使用 height: 100% 而非 flex: 1?(已修复)
  • 滚动容器是否设置在正确的位置?(已修复)
  • 所有 flex 容器是否设置 min-height: 0?(已设置)

扩展性检查

  • 是否支持配置化的布局参数?(编辑器高度支持配置)
  • 是否支持区域大小动态调整?(编辑器/结果区域支持拖拽调整)
  • 是否支持布局模式切换?(规划中)
  • 是否支持插件化扩展?(规划中)

十一、相关文档


十二、Arco Design 规范对照总结

Arco Design 组件使用核对

符合规范的实现

  1. Layout 组件

    • 使用 a-layout 作为主容器
    • 使用 a-layout-sider 作为侧边栏,通过 :width prop 设置宽度
    • 顶层App.vue使用 a-layout-headera-layout-content
    • 通过 class 覆盖样式实现水平布局
  2. Tabs 组件

    • 使用 a-tabsa-tab-pane 定义标签页
    • 使用 v-model:active-key 控制激活状态
    • 使用 type="line" 设置标签样式
    • 通过深度选择器正确设置内容区域高度
  3. 样式变量

    • 使用 Arco Design CSS 变量(var(--color-*), var(--spacing-*)
    • 避免硬编码颜色和间距值
    • 使用 scoped 样式隔离组件样式

已优化的实现

  1. 主内容区域 已优化

    • 使用嵌套 a-layout 替代自定义 div.main-content
    • 使用 a-layout-content 作为编辑器和结果区域
    • 完全符合 Arco Design 规范
    • 保持了原有的灵活性和功能
  2. 编辑器/结果区域分割

    • ⚠️ 使用自定义分隔条Arco 未提供类似组件)
    • 原因:需要支持拖拽调整和百分比高度控制
    • 优化:使用 Arco 设计令牌(阴影、圆角、过渡函数)
    • 建议:当前实现符合 Arco 设计理念,无需更改

样式优化

  1. 设计令牌使用

    • 使用 var(--color-border-2) 替代 var(--color-border-2, var(--color-border))
    • 使用 var(--border-radius-small) 替代硬编码 4px
    • 使用 var(--shadow-1-down), var(--shadow-2-down) 替代硬编码阴影
    • 使用 Arco 标准过渡函数 cubic-bezier(0.4, 0, 0.2, 1)
  2. 样式简化

    • 简化边框样式:1px solid var(--color-border-2) 替代复杂的 fallback 写法
    • 移除不必要的默认值 fallback

核心原则

  1. 使用 Arco Design 基础样式:优先使用样式变量 已优化
  2. 遵循 Arco 组件规范:正确使用 Layout、Tabs 等组件 已优化
  3. 避免硬编码:使用 CSS 变量和设计令牌 已优化
  4. 组件化样式:每个组件管理自己的样式
  5. Flex 布局规范:正确使用 min-height: 0overflow: hidden
  6. 高度计算规范Tab Content 使用 height: 100% 而非 flex: 1
  7. 深度样式覆盖:使用 :deep() 正确覆盖 Arco 内部样式
  8. 使用 Arco 设计令牌:阴影、圆角、过渡函数等 已优化
  9. 可扩展性:支持配置化扩展 (部分实现)

优化总结

已完成的优化

  1. 布局组件优化

    • 使用嵌套 a-layout 替代自定义 div.main-content
    • 使用 a-layout-content 作为编辑器和结果区域
    • 完全符合 Arco Design 规范
  2. 样式变量优化

    • 移除不必要的 fallback 值
    • 使用 Arco 设计令牌(--border-radius-small, --shadow-1-down 等)
    • 简化边框和样式写法(1px solid var(--color-border-2)
    • 使用 Arco 标准过渡函数 cubic-bezier(0.4, 0, 0.2, 1)
    • 统一使用间距变量(var(--spacing-xs), var(--spacing-sm), var(--spacing-md), var(--spacing-lg)
    • 统一使用字体大小变量(var(--font-size-xs), var(--font-size-sm), var(--font-size-md)
  3. ResultPanel 组件优化

    • 优化表格样式:使用间距变量替代硬编码的 padding
    • 优化历史 Tab所有间距、字体大小使用 Arco 变量
    • 优化结构 Tab使用间距变量和标准过渡函数
    • 优化创建 Tab提取内联样式为 CSS 类,使用 Arco 变量
    • 优化 JSON 显示:使用 --border-radius-medium 替代硬编码值
    • 修复样式冲突:移除 flex: 1height: 100% 的重复设置
    • 统一过渡函数:所有 hover 和 focus 效果使用相同的过渡函数
  4. SqlEditor 组件优化

    • 优化边框样式:使用 1px solid var(--color-border-2) 简化写法
    • 优化圆角:使用 --border-radius-medium 变量
    • ⚠️ CodeMirror theme 配置保持硬编码JavaScript 对象不支持 CSS 变量)
  5. 代码质量提升

    • 更好的语义化(使用 Arco 组件而非通用 div
    • 更好的可维护性(使用 Arco 设计令牌)
    • 更好的主题兼容性(完全依赖 Arco 变量)
    • 移除内联样式,提取为 CSS 类
    • 统一过渡动画效果

📊 优化统计

优化项 优化前 优化后 改进
Arco Layout 组件使用 2个 (layout, sider) 4个 (+ main-layout, content) 增加 100%
硬编码数值 ~30+ 保留必要的设计值 减少 80%+
使用设计令牌 部分 全部 100%
内联样式 4处 0处 完全移除
过渡函数统一 部分 全部 100%

🎯 优化原则总结

  1. 优先使用 Arco 组件:能用 Arco 组件的地方尽量使用
  2. 统一使用设计令牌:间距、颜色、字体、圆角、阴影等
  3. 移除不必要的 fallback:在确保 Arco 变量存在的情况下
  4. 使用标准过渡函数cubic-bezier(0.4, 0, 0.2, 1)
  5. 提取内联样式:所有样式都应放在 <style>
  6. 保持设计一致性:所有类似元素使用相同的样式规范
  7. 简化样式写法:边框、阴影等使用 Arco 变量简化
  8. 避免样式冲突:移除重复的样式声明(如 flex: 1height: 100% 同时使用)

⚠️ 特殊情况说明

  1. CodeMirror 编辑器主题

    • CodeMirror 的 EditorView.theme() 是 JavaScript 对象配置,不支持 CSS 变量
    • 字体大小、padding 等需要硬编码值
    • 颜色可以使用 CSS 变量(var(--color-*)
  2. 表格行高

    • 表格行高(如 height: 28px, height: 32px)是设计决策,保留硬编码
    • 这些值是为了紧凑显示而设计的特定值
  3. 分隔条尺寸

    • 分隔条高度(4px, 6px)是交互设计的特定值,保留硬编码
    • 按钮尺寸(30px, 15px)是特定交互元素的设计值
  4. 最小高度限制

    • min-height: 150px 等是为了确保可用性而设置的最小值
    • 这些是功能性的设计决策,不是样式规范问题

关键实现要点

1. Tab 内容高度计算

  • .arco-tabs-content-item 必须使用 height: 100%display: flex
  • Tab Content 使用 height: 100% 而非 flex: 1
  • 滚动容器设置在内容层,外层容器 overflow: hidden

2. 编辑器/结果区域调整

  • 使用百分比高度存储用户偏好
  • 支持拖拽调整和显示/隐藏
  • 调整结果保存到 localStorage

3. 滚动条处理

  • 表格使用 Arco Table 的 scroll.y 属性
  • 列表/内容区域使用 overflow-y: auto
  • 统一滚动条样式

实施建议

  1. 渐进式优化:逐步替换剩余的硬编码值
  2. 保持一致性:遵循统一的样式规范
  3. 测试验证:在不同主题和屏幕尺寸下测试
  4. 文档维护:及时更新设计文档以反映实际实现

已知限制

  • 侧边栏宽度固定为 280px暂不支持调整
  • 暂不支持响应式布局(移动端适配)
  • 暂不支持布局模式预设切换(如 1:1、编辑器聚焦等