CLI 使用示例

在页面中集成CLI终端

示例1:独立的CLI页面

创建新页面 src/pages/CLI/index.tsx:

import React from 'react'
import { CLITerminal } from '@/components/cli/CLITerminal'

export default function CLIPage() {
  return (
    <div className="h-screen">
      <CLITerminal />
    </div>
  )
}

示例2:在设置页面中添加CLI标签页

import React, { useState } from 'react'
import { CLITerminal } from '@/components/cli/CLITerminal'

export default function SettingsPage() {
  const [activeTab, setActiveTab] = useState('general')

  return (
    <div className="h-screen flex flex-col">
      <div className="border-b">
        <button onClick={() => setActiveTab('general')}>常规</button>
        <button onClick={() => setActiveTab('cli')}>CLI终端</button>
      </div>
      
      <div className="flex-1">
        {activeTab === 'cli' && <CLITerminal />}
        {activeTab === 'general' && <div>常规设置...</div>}
      </div>
    </div>
  )
}

示例3:在编辑器页面中集成CLI面板

import React, { useState } from 'react'
import { CLITerminal } from '@/components/cli/CLITerminal'

export default function EditorPage() {
  const [showCLI, setShowCLI] = useState(false)

  return (
    <div className="h-screen flex flex-col">
      <div className="flex-1">
        {/* 编辑器内容 */}
        <div>代码编辑器...</div>
      </div>
      
      {/* CLI面板(可折叠) */}
      {showCLI && (
        <div className="h-64 border-t">
          <div className="flex justify-between items-center p-2 bg-gray-800">
            <span className="text-white">CLI终端</span>
            <button onClick={() => setShowCLI(false)}>关闭</button>
          </div>
          <div className="h-56">
            <CLITerminal />
          </div>
        </div>
      )}
      
      {!showCLI && (
        <button onClick={() => setShowCLI(true)} className="p-2 bg-gray-800 text-white">
          打开CLI终端
        </button>
      )}
    </div>
  )
}

编程式调用CLI

示例1:检查系统状态

import { cliService } from '@/services/cliService'
import { useState } from 'react'

function StatusChecker() {
  const [status, setStatus] = useState<string>('')

  const checkStatus = async () => {
    setStatus('检查中...')
    
    let output = ''
    await cliService.execute(
      { command: 'status' },
      {
        onOutput: (data) => {
          output += data.data
          setStatus(output)
        },
        onComplete: () => {
          setStatus(output)
        },
        onError: (error) => {
          setStatus(`错误: ${error}`)
        },
      }
    )
  }

  return (
    <div>
      <button onClick={checkStatus}>检查状态</button>
      <pre className="bg-gray-900 text-green-400 p-4 rounded">
        {status}
      </pre>
    </div>
  )
}

示例2:获取用户列表

import { executeCLI } from '@/services/cliService'

async function getUserList() {
  const users: string[] = []
  
  await executeCLI('users', [], {
    onOutput: (data) => {
      // 解析输出,提取用户信息
      const lines = data.data.split('\n')
      lines.forEach(line => {
        if (line.trim() && !line.includes('ID')) {
          users.push(line.trim())
        }
      })
    },
  })
  
  return users
}

示例3:执行聊天命令

import { cliService } from '@/services/cliService'

async function chatWithExpert(expertId: string, message: string) {
  const requestId = await cliService.execute(
    {
      command: 'chat',
      args: [message],
      options: {
        expert: expertId,
        interactive: false,
      },
    },
    {
      onOutput: (data) => {
        // 实时显示AI回复
        console.log('AI:', data.data)
      },
    }
  )
  
  return requestId
}

示例4:批量操作知识库

import { cliService } from '@/services/cliService'

async function exportAllKnowledgeBases() {
  await cliService.execute(
    { command: 'kbs', args: ['--export', 'all'] },
    {
      onOutput: (data) => {
        // 显示导出进度
        console.log(data.data)
      },
      onComplete: (exitCode) => {
        if (exitCode === 0) {
          console.log('导出成功')
        } else {
          console.error('导出失败')
        }
      },
    }
  )
}

错误处理

检查CLI是否可用

import { cliService } from '@/services/cliService'

function MyComponent() {
  if (!cliService.isAvailable()) {
    return <div>CLI功能不可用,请确保在Electron环境中运行</div>
  }
  
  // 使用CLI功能...
}

处理错误

try {
  await cliService.execute({ command: 'status' }, {
    onError: (error) => {
      // 显示错误提示
      toast.error(`CLI错误: ${error}`)
    },
  })
} catch (error) {
  // 处理初始化错误
  console.error('无法执行CLI命令:', error)
}

高级用法

命令历史记录

import { useState } from 'react'
import { cliService } from '@/services/cliService'

function CLITerminalWithHistory() {
  const [history, setHistory] = useState<string[]>([])
  const [historyIndex, setHistoryIndex] = useState(-1)

  const executeCommand = async (command: string) => {
    // 添加到历史记录
    setHistory(prev => [...prev, command])
    setHistoryIndex(-1)
    
    // 执行命令
    await cliService.execute({ command })
  }

  const navigateHistory = (direction: 'up' | 'down') => {
    if (direction === 'up' && historyIndex < history.length - 1) {
      setHistoryIndex(prev => prev + 1)
      return history[history.length - 1 - historyIndex - 1]
    } else if (direction === 'down' && historyIndex > 0) {
      setHistoryIndex(prev => prev - 1)
      return history[history.length - 1 - historyIndex + 1]
    }
    return ''
  }

  return (
    // 实现带历史记录的终端...
  )
}

命令自动补全

const CLI_COMMANDS = [
  'status',
  'users',
  'experts',
  'kbs',
  'chat',
  'logs',
  'benchmark',
]

function AutoCompleteInput() {
  const [input, setInput] = useState('')
  const [suggestions, setSuggestions] = useState<string[]>([])

  const handleInputChange = (value: string) => {
    setInput(value)
    
    if (value.trim()) {
      const matches = CLI_COMMANDS.filter(cmd => 
        cmd.startsWith(value.toLowerCase())
      )
      setSuggestions(matches)
    } else {
      setSuggestions([])
    }
  }

  return (
    <div className="relative">
      <input
        value={input}
        onChange={(e) => handleInputChange(e.target.value)}
        onKeyDown={(e) => {
          if (e.key === 'Tab' && suggestions.length > 0) {
            e.preventDefault()
            setInput(suggestions[0])
            setSuggestions([])
          }
        }}
      />
      {suggestions.length > 0 && (
        <div className="absolute top-full left-0 bg-gray-800 border border-gray-700 rounded">
          {suggestions.map(suggestion => (
            <div key={suggestion} className="p-2 hover:bg-gray-700">
              {suggestion}
            </div>
          ))}
        </div>
      )}
    </div>
  )
}

新增 CLI 命令示例(Phase 7 新增)

订阅管理

// 查询订阅方案
const plans = await cliService.execute('subscription', 'plans', { json: true })

// 查询用户订阅统计
const stats = await cliService.execute('subscription', 'stats', { json: true })

// 查询优惠券
const coupons = await cliService.execute('subscription', 'coupons', { json: true })

IoT 终端

// 全量终端状态检测
const iotStatus = await cliService.execute('iot', 'status', { json: true })
// 返回: { online_count: 5, offline_count: 3, total_types: 8 }

// 终端健康检查(含延迟)
const iotHealth = await cliService.execute('iot', 'health', { json: true })

// 设备类型
const iotTypes = await cliService.execute('iot', 'types', { json: true })

文档系统

// 生成文档(异步)
const doc = await cliService.execute('document', 'generate', {
  args: ['--industry', 'insurance', '--type', 'claim', '--format', 'pdf'],
  json: true
})
// 返回: { document_id: "doc_abc123" }

// 查询生成状态
const status = await cliService.execute('document', 'status', {
  args: ['--id', doc.data.document_id],
  json: true
})

MOE/集群管理

// MOE 健康
const moeHealth = await cliService.execute('cluster', 'moe-health', { json: true })

// GPU 节点
const gpuNodes = await cliService.execute('cluster', 'gpu-nodes', { json: true })

// A/B 测试
const abTests = await cliService.execute('cluster', 'ab-tests', { json: true })

自测与仓库

// CLI 自测(快速模式)
const test = await cliService.execute('self-test', 'run', {
  args: ['--quick'],
  json: true
})
// 返回: { total_pass: 102, total_fail: 0 }

// 多仓库状态
const repoStatus = await cliService.execute('repo', 'status', { json: true })

最佳实践

  1. 检查可用性: 始终检查 cliService.isAvailable() 再使用
  2. 清理资源: 组件卸载时清理监听器
  3. 错误处理: 始终提供错误回调
  4. 用户体验: 显示加载状态和进度
  5. 安全性: 验证用户输入,防止命令注入

故障排查

CLI命令不执行

  1. 检查Python是否安装:python --version
  2. 检查CLI脚本路径是否正确
  3. 检查后端API是否运行:http://localhost:8000
  4. 查看Electron主进程日志

输出不显示

  1. 检查IPC通信是否正常
  2. 检查preload脚本是否正确加载
  3. 检查渲染进程是否正确监听事件

命令被终止

  1. 检查是否有权限问题
  2. 检查Python环境变量
  3. 查看错误输出(stderr)