# 通用组件使用指南

本文档介绍5个新创建的通用组件的使用方法和API。

## 🔧 A) XtStickyActionBar - 底部粘性操作栏

### 功能描述
底部固定的操作栏，显示状态信息和操作按钮，支持响应式设计和明暗主题。

### Props
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| dirtyCount | Number | 0 | 变更项数量 |
| errorCount | Number | 0 | 错误项数量 |
| loading | Object | `{}` | 加载状态对象 |
| showProgress | Boolean | false | 是否显示进度条 |
| progressPercent | Number | 0 | 进度百分比(0-100) |

### Events
| 事件名 | 参数 | 说明 |
|--------|------|------|
| save | - | 保存草稿 |
| test | - | 测试全部 |
| publish | - | 发布 |
| rollback | - | 回滚 |
| reset | - | 重置变更 |
| export | - | 导出配置 |

### 使用示例
```vue
<template>
  <div>
    <!-- 页面内容 -->
    <div class="page-content">
      <!-- ... -->
    </div>
    
    <!-- 底部操作栏 -->
    <XtStickyActionBar
      :dirty-count="formChanges.length"
      :error-count="validationErrors.length"
      :loading="actionLoading"
      :show-progress="isProcessing"
      :progress-percent="processPercent"
      @save="handleSaveDraft"
      @test="handleTestAll"
      @publish="handlePublish"
      @rollback="handleRollback"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      formChanges: [],
      validationErrors: [],
      actionLoading: {
        save: false,
        test: false,
        publish: false,
        rollback: false
      },
      isProcessing: false,
      processPercent: 0
    }
  },
  
  methods: {
    handleSaveDraft() {
      this.actionLoading.save = true
      // 保存逻辑
    },
    
    handleTestAll() {
      this.actionLoading.test = true
      // 测试逻辑
    },
    
    handlePublish() {
      if (this.validationErrors.length > 0) {
        this.$message.error('请先修复所有错误')
        return
      }
      this.actionLoading.publish = true
      // 发布逻辑
    }
  }
}
</script>
```

---

## 📋 B) XtGroupedFormCard - 分组表单卡片

### 功能描述
可折叠的分组表单卡片，支持自定义操作按钮和过渡动画。

### Props
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | String | - | 卡片标题（必填） |
| desc | String | '' | 卡片描述 |
| collapsible | Boolean | true | 是否可折叠 |
| defaultCollapsed | Boolean | false | 默认是否折叠 |

### Events
| 事件名 | 参数 | 说明 |
|--------|------|------|
| test | - | 测试按钮点击 |
| reset | - | 重置按钮点击 |
| toggle | collapsed | 折叠状态变化 |

### Slots
| 插槽名 | 说明 |
|--------|------|
| default | 表单内容区域 |
| actions | 自定义右上角操作按钮 |

### 使用示例
```vue
<template>
  <div class="form-container">
    <XtGroupedFormCard
      title="数据库配置"
      desc="配置数据库连接参数"
      :collapsible="true"
      :default-collapsed="false"
      @test="testDbConnection"
      @reset="resetDbConfig"
      @toggle="handleToggle"
    >
      <!-- 自定义操作按钮 -->
      <template #actions>
        <el-button
          type="text"
          size="small"
          icon="el-icon-connection"
          @click="testConnection"
        >
          测试连接
        </el-button>
      </template>
      
      <!-- 表单内容 -->
      <el-form :model="dbConfig" label-width="120px">
        <el-form-item label="主机地址">
          <el-input v-model="dbConfig.host" placeholder="localhost" />
        </el-form-item>
        
        <el-form-item label="端口">
          <el-input v-model="dbConfig.port" placeholder="3306" />
        </el-form-item>
        
        <el-form-item label="数据库名">
          <el-input v-model="dbConfig.database" placeholder="database_name" />
        </el-form-item>
        
        <!-- 表单分组 -->
        <div class="form-group">
          <div class="form-group-title">认证信息</div>
          <el-form-item label="用户名">
            <el-input v-model="dbConfig.username" />
          </el-form-item>
          <el-form-item label="密码">
            <el-input v-model="dbConfig.password" type="password" show-password />
          </el-form-item>
        </div>
      </el-form>
    </XtGroupedFormCard>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dbConfig: {
        host: '',
        port: '',
        database: '',
        username: '',
        password: ''
      }
    }
  },
  
  methods: {
    testDbConnection() {
      console.log('测试数据库连接')
    },
    
    resetDbConfig() {
      this.dbConfig = {
        host: '',
        port: '',
        database: '',
        username: '',
        password: ''
      }
    },
    
    handleToggle(collapsed) {
      console.log('折叠状态:', collapsed)
    }
  }
}
</script>
```

---

## 🔗 C) XtTestConnectionDrawer - 测试连接抽屉

### 功能描述
右侧抽屉展示测试连接的时间轴日志，支持重新测试和日志管理。

### Props
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| visible | Boolean | false | 是否显示抽屉 |
| title | String | '连接测试' | 抽屉标题 |
| logs | Array | [] | 测试日志数组 |
| loading | Boolean | false | 加载状态 |

### Events
| 事件名 | 参数 | 说明 |
|--------|------|------|
| close | - | 关闭抽屉 |
| retest | - | 重新测试 |
| clear-logs | - | 清空日志 |

### 日志数据格式
```javascript
{
  ts: 1640995200000,           // 时间戳
  step: '连接数据库',           // 步骤名称
  status: 'ok',                // 状态: 'ok'|'warn'|'fail'
  cost: 120,                   // 耗时(ms)
  tip: '连接成功',             // 提示信息
  details: '详细日志信息...'    // 详细信息(可选)
}
```

### 使用示例
```vue
<template>
  <div>
    <el-button @click="showTestDrawer = true">测试连接</el-button>
    
    <XtTestConnectionDrawer
      :visible="showTestDrawer"
      title="Redis 连接测试"
      :logs="testLogs"
      :loading="testing"
      @close="showTestDrawer = false"
      @retest="startConnectionTest"
      @clear-logs="clearTestLogs"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      showTestDrawer: false,
      testing: false,
      testLogs: [
        {
          ts: Date.now() - 5000,
          step: '解析连接地址',
          status: 'ok',
          cost: 10,
          tip: '地址解析成功: redis://localhost:6379'
        },
        {
          ts: Date.now() - 4000,
          step: '建立TCP连接',
          status: 'ok',
          cost: 150,
          tip: 'TCP连接建立成功'
        },
        {
          ts: Date.now() - 3000,
          step: '身份认证',
          status: 'warn',
          cost: 200,
          tip: '未配置密码，使用默认认证'
        },
        {
          ts: Date.now() - 2000,
          step: '执行PING命令',
          status: 'ok',
          cost: 5,
          tip: '服务器响应: PONG'
        }
      ]
    }
  },
  
  methods: {
    async startConnectionTest() {
      this.testing = true
      this.testLogs = []
      
      try {
        // 模拟测试步骤
        await this.runTestStep('连接服务器', 100)
        await this.runTestStep('验证权限', 200)
        await this.runTestStep('测试读写', 150)
        
        this.$message.success('连接测试完成')
      } catch (error) {
        this.$message.error('连接测试失败')
      } finally {
        this.testing = false
      }
    },
    
    async runTestStep(stepName, duration) {
      const startTime = Date.now()
      
      // 模拟异步操作
      await new Promise(resolve => setTimeout(resolve, duration))
      
      const cost = Date.now() - startTime
      const log = {
        ts: Date.now(),
        step: stepName,
        status: Math.random() > 0.8 ? 'warn' : 'ok',
        cost,
        tip: `${stepName}完成，耗时${cost}ms`
      }
      
      this.testLogs.push(log)
    },
    
    clearTestLogs() {
      this.testLogs = []
    }
  }
}
</script>
```

---

## 📊 D) XtDiffPublishDialog - 差异发布对话框

### 功能描述
展示配置变更的对比对话框，支持选择性发布和搜索过滤。

### Props
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| visible | Boolean | false | 是否显示对话框 |
| diffs | Array | [] | 差异数据数组 |
| loading | Boolean | false | 加载状态 |
| publishing | Boolean | false | 发布状态 |

### Events
| 事件名 | 参数 | 说明 |
|--------|------|------|
| confirm | selectedKeys | 确认发布，返回选中的key数组 |
| cancel | - | 取消发布 |

### 差异数据格式
```javascript
{
  key: 'database.host',        // 配置键
  name: '数据库主机',          // 显示名称
  path: 'config.database',     // 配置路径
  oldValue: 'localhost',       // 原值
  newValue: '192.168.1.100',   // 新值
  isChanged: true,             // 是否变更
  isNew: false,                // 是否新增
  isDeleted: false,            // 是否删除
  description: '主机地址变更'   // 变更说明
}
```

### 使用示例
```vue
<template>
  <div>
    <el-button @click="showPublishDialog = true">发布配置</el-button>
    
    <XtDiffPublishDialog
      :visible="showPublishDialog"
      :diffs="configDiffs"
      :loading="loadingDiffs"
      :publishing="publishingConfig"
      @confirm="handlePublishConfirm"
      @cancel="showPublishDialog = false"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      showPublishDialog: false,
      loadingDiffs: false,
      publishingConfig: false,
      configDiffs: [
        {
          key: 'database.host',
          name: '数据库主机',
          path: 'config.database',
          oldValue: 'localhost',
          newValue: '192.168.1.100',
          isChanged: true,
          isNew: false,
          isDeleted: false,
          description: '切换到生产环境数据库'
        },
        {
          key: 'redis.port',
          name: 'Redis端口',
          path: 'config.redis',
          oldValue: 6379,
          newValue: 6380,
          isChanged: true,
          isNew: false,
          isDeleted: false,
          description: '避免端口冲突'
        },
        {
          key: 'app.debug',
          name: '调试模式',
          path: 'config.app',
          oldValue: true,
          newValue: null,
          isChanged: false,
          isNew: false,
          isDeleted: true,
          description: '生产环境关闭调试'
        }
      ]
    }
  },
  
  methods: {
    async handlePublishConfirm(selectedKeys) {
      this.publishingConfig = true
      
      try {
        // 发布选中的配置项
        await this.publishConfigs(selectedKeys)
        
        this.$message.success(`成功发布 ${selectedKeys.length} 项配置`)
        this.showPublishDialog = false
        
        // 刷新配置列表
        this.loadConfigs()
      } catch (error) {
        this.$message.error('发布失败: ' + error.message)
      } finally {
        this.publishingConfig = false
      }
    },
    
    async publishConfigs(keys) {
      // 模拟发布API调用
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (Math.random() > 0.1) {
            resolve()
          } else {
            reject(new Error('网络错误'))
          }
        }, 2000)
      })
    }
  }
}
</script>
```

---

## 📈 E) XtRightSummaryPanel - 右侧摘要面板

### 功能描述
右侧固定的摘要面板，显示统计信息、配置项状态和快速操作。

### Props
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| stats | Object | `{}` | 统计数据对象 |
| items | Array | [] | 配置项数组 |
| loading | Boolean | false | 加载状态 |
| activeItemKey | String | '' | 当前激活的配置项key |

### Events
| 事件名 | 参数 | 说明 |
|--------|------|------|
| item-click | item | 配置项点击 |
| publish-changes | - | 发布变更 |
| fix-risks | - | 修复风险 |
| test-all | - | 重新测试 |

### 统计数据格式
```javascript
{
  changed: 5,              // 变更数量
  passed: 12,              // 通过数量
  risk: 2,                 // 风险数量
  lastTestAt: 1640995200000 // 最后测试时间
}
```

### 配置项数据格式
```javascript
{
  key: 'database.host',           // 配置键
  name: '数据库主机',             // 显示名称
  path: 'config.database',        // 配置路径
  group: 'Database',              // 分组
  status: 'passed',               // 状态: 'passed'|'risk'|'pending'|'changed'
  isChanged: false                // 是否变更
}
```

### 使用示例
```vue
<template>
  <div class="config-page">
    <!-- 主内容区域 -->
    <div class="main-content">
      <!-- 配置表单等内容 -->
    </div>
    
    <!-- 右侧摘要面板 -->
    <XtRightSummaryPanel
      :stats="configStats"
      :items="configItems"
      :loading="loadingStats"
      :active-item-key="activeConfigKey"
      @item-click="handleItemClick"
      @publish-changes="handlePublishChanges"
      @fix-risks="handleFixRisks"
      @test-all="handleTestAll"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      loadingStats: false,
      activeConfigKey: '',
      configStats: {
        changed: 3,
        passed: 15,
        risk: 1,
        lastTestAt: Date.now() - 300000 // 5分钟前
      },
      configItems: [
        {
          key: 'database.host',
          name: '数据库主机',
          path: 'config.database',
          group: 'Database',
          status: 'changed',
          isChanged: true
        },
        {
          key: 'redis.port',
          name: 'Redis端口',
          path: 'config.redis',
          group: 'Cache',
          status: 'passed',
          isChanged: false
        },
        {
          key: 'app.secret',
          name: '应用密钥',
          path: 'config.app',
          group: 'Security',
          status: 'risk',
          isChanged: false
        }
      ]
    }
  },
  
  methods: {
    handleItemClick(item) {
      this.activeConfigKey = item.key
      // 跳转到对应的配置项
      this.scrollToConfigItem(item.key)
    },
    
    handlePublishChanges() {
      // 打开发布对话框
      this.showPublishDialog = true
    },
    
    handleFixRisks() {
      // 处理风险配置项
      const riskItems = this.configItems.filter(item => item.status === 'risk')
      this.showRiskFixDialog(riskItems)
    },
    
    handleTestAll() {
      // 重新测试所有配置
      this.runFullTest()
    },
    
    scrollToConfigItem(key) {
      const element = document.getElementById(`config-${key}`)
      if (element) {
        element.scrollIntoView({ behavior: 'smooth' })
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.config-page {
  display: flex;
  height: 100vh;

  .main-content {
    flex: 1;
    overflow-y: auto;
    padding: var(--spacing-6);
  }
}
</style>
```

---

## 🎨 主题适配

所有组件都完全支持明暗主题切换，使用了设计令牌系统中的颜色变量。组件会自动响应主题变化，无需额外配置。

## 📱 响应式设计

所有组件都内置了响应式设计支持：

- **移动端优化**：在小屏幕设备上自动调整布局
- **触摸友好**：按钮和交互元素针对触摸操作优化
- **自适应尺寸**：根据容器大小自动调整组件尺寸

## 🔧 自定义样式

如需自定义组件样式，可以通过以下方式：

1. **使用设计令牌**：修改CSS变量来调整主题色彩
2. **CSS类覆盖**：使用更高优先级的CSS类覆盖默认样式
3. **插槽定制**：利用组件提供的插槽来自定义内容

## 🚀 性能优化

- **虚拟滚动**：大列表组件支持虚拟滚动
- **懒加载**：按需加载数据和组件
- **防抖节流**：搜索和频繁操作使用防抖节流
- **内存管理**：组件销毁时正确清理事件监听器

## 📞 技术支持

如有任何问题或建议，请联系前端开发团队。

**Happy Coding! 🎉**
