# 设置面板 UI 改进总结

## 问题修复

### 1. 保存后未立即生效 ✅

**原因分析：**
- `tabs` 数组中的 `visible` 属性与 `visibleTabs` 数组不同步
- `watch(selectedTabs)` 覆盖了拖拽排序的顺序

**修复方案：**
1. 在 `handleTabVisibilityChange` 中同步更新 `tabs` 数组的 `visible` 属性
2. 移除 `watch(selectedTabs)`，避免覆盖排序
3. 在 `handleSave` 中确保数据完全同步
4. 在 `loadConfig` 中从后端加载时同步 `visible` 属性

### 2. UI 合并优化 ✅

**改进前：**
- Tab 显示、默认 Tab、拖拽排序分成三个独立的卡片
- 用户需要在不同区域操作，不够直观

**改进后：**
- 统一到一个列表中，每行包含所有控制项
- 更直观、更高效的配置体验

## 新的 UI 设计

### Tab 配置列表结构

```
┌─────────────────────────────────────────────────────┐
│ ℹ️ 拖拽可调整 Tab 顺序，勾选复选框控制显示，单选按钮  │
│    设置默认打开的 Tab                                  │
├─────────────────────────────────────────────────────┤
│ ⋮  ☑  数据库        ○ 默认打开                       │
│ ⋮  ☑  文件管理      ○ 默认打开                       │
│ ⋮  ☑  设备调用测试  ⦿ 默认打开                       │
├─────────────────────────────────────────────────────┤
│ 隐藏的 Tabs                                           │
├─────────────────────────────────────────────────────┤
│ ⋮  ☐  （其他隐藏的 Tab）                              │
└─────────────────────────────────────────────────────┘
```

### 每行包含的元素

1. **拖拽手柄** (⋮) - 拖拽调整顺序
2. **复选框** (☑/☐) - 控制显示/隐藏
3. **Tab 标题** - 显示 Tab 名称
4. **单选按钮** (⦿) - 设置默认打开的 Tab

## 技术实现

### 新增辅助函数

```javascript
// 判断 Tab 是否可见
const isTabVisible = (key) => {
  return localConfig.value.visibleTabs.includes(key)
}

// 判断 Tab 是否启用
const isTabEnabled = (key) => {
  const tab = localConfig.value.tabs.find(t => t.key === key)
  return tab ? tab.enabled : false
}

// 隐藏的 Tabs 计算属性
const hiddenTabs = computed(() => {
  return localConfig.value.tabs.filter(
    tab => !localConfig.value.visibleTabs.includes(tab.key)
  )
})
```

### 改进的可见性处理

```javascript
// 处理单个 Tab 可见性变化
const handleTabVisibilityChange = (tabKey, visible) => {
  if (visible) {
    // 显示 Tab：添加到 visibleTabs 末尾
    localConfig.value.visibleTabs.push(tabKey)
  } else {
    // 隐藏 Tab：从 visibleTabs 中移除
    // 至少保留一个 Tab
    if (localConfig.value.visibleTabs.length <= 1) {
      Message.warning('至少需要保留一个可见的 Tab')
      return
    }

    // 如果隐藏的是默认 Tab，需要更改默认 Tab
    if (localConfig.value.defaultTab === tabKey) {
      const remainingTabs = localConfig.value.visibleTabs.filter(k => k !== tabKey)
      localConfig.value.defaultTab = remainingTabs[0] || ''
    }

    localConfig.value.visibleTabs = localConfig.value.visibleTabs.filter(
      k => k !== tabKey
    )
  }

  // 同步更新 tabs 数组中的 visible 属性
  localConfig.value.tabs = localConfig.value.tabs.map(tab => ({
    ...tab,
    visible: localConfig.value.visibleTabs.includes(tab.key)
  }))
}
```

### 保存前数据同步

```javascript
// 保存配置
const handleSave = async () => {
  // ... 验证逻辑 ...

  // 确保 tabs 数组中的 visible 属性与 visibleTabs 完全同步
  const syncedTabs = localConfig.value.tabs.map(tab => ({
    ...tab,
    visible: localConfig.value.visibleTabs.includes(tab.key)
  }))

  const configToSave = {
    tabs: syncedTabs,
    visibleTabs: [...localConfig.value.visibleTabs],
    defaultTab: localConfig.value.defaultTab
  }

  // ... 保存逻辑 ...
}
```

## 样式改进

### 配置项样式

```css
.tab-config-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--color-fill-1);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  cursor: move;
  transition: all 0.2s;
}

.tab-config-item:hover {
  background: var(--color-fill-2);
  border-color: var(--color-border-2);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.tab-config-item.dragging {
  opacity: 0.5;
  background: var(--color-fill-2);
  transform: scale(0.98);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
```

### 隐藏项样式

```css
.tab-config-item.hidden {
  opacity: 0.6;
  cursor: default;
}

.tab-config-item.hidden:hover {
  border-color: var(--color-border);
  box-shadow: none;
}
```

## 用户体验改进

1. **一目了然** - 所有配置集中在一行，无需来回查看
2. **即时反馈** - 拖拽时有视觉反馈（透明度、缩放、阴影）
3. **智能提示** - 顶部说明文字告知用户如何操作
4. **分组显示** - 可见和隐藏的 Tab 分开展示
5. **保护机制** - 至少保留一个可见 Tab，最后一个 Tab 的复选框禁用

## 数据流保证

### 配置加载
```
后端 → GetAppConfig → loadConfig → 同步 visible 属性 → 显示
```

### 配置保存
```
用户操作 → localConfig → handleSave → 同步数据 → 后端保存 → 刷新 UI
```

### 关键同步点

1. **复选框改变** → 同步 `visibleTabs` 和 `tabs[].visible`
2. **拖拽排序** → 更新 `visibleTabs` 顺序
3. **保存前** → 确保所有 `visible` 属性与 `visibleTabs` 一致
4. **加载后** → 根据后端数据同步 `visible` 属性

## 测试清单

### 基础功能
- ✅ 拖拽排序 Tab
- ✅ 勾选/取消勾选复选框
- ✅ 设置默认 Tab
- ✅ 保存配置后立即生效
- ✅ 刷新页面后配置保持

### 边界情况
- ✅ 至少保留一个可见 Tab
- ✅ 隐藏默认 Tab 时自动切换
- ✅ 禁用的 Tab 不可操作
- ✅ 配置为空时显示默认值

### UI 交互
- ✅ 拖拽时视觉反馈
- ✅ hover 状态提示
- ✅ 隐藏项分组显示
- ✅ 说明文字清晰

## 修复文件

- `frontend/src/components/SettingsPanel.vue` - UI 合并和逻辑修复
- `frontend/src/App.vue` - loadConfig 和 handleSaveConfig 数据同步

## 总结

本次改进解决了两个主要问题：
1. **保存后未立即生效** - 通过数据同步机制修复
2. **UI 不够直观** - 通过统一配置列表优化

用户体验得到显著提升，配置操作更加高效和直观。
