/** * SlashCommandMenu — / 命令选择菜单 * * 用户输入 / 时弹出的命令搜索和选择面板。 */ import { useTranslation } from 'react-i18next' import { useState, useEffect, useRef, useCallback } from 'react' import { Sparkles, Zap } from 'lucide-react' import { searchSlashCommands, type SlashCommand } from '../../../services/agent/intent-router' interface Props { /** 搜索关键词(/ 后面的文字) */ query: string /** 选择命令的回调 */ onSelect: (command: SlashCommand) => void /** 关闭菜单 */ onClose: () => void /** 菜单位置 */ position?: { bottom: number; left: number } } export default function SlashCommandMenu({ query, onSelect, onClose, position }: Props) { const { t } = useTranslation('panels') const [selectedIndex, setSelectedIndex] = useState(0) const menuRef = useRef(null) const results = searchSlashCommands(query) const [prevQuery, setPrevQuery] = useState(query) // 重置选中索引 if (query !== prevQuery) { setSelectedIndex(0) setPrevQuery(query) } // 键盘导航 const handleKeyDown = useCallback((e: KeyboardEvent) => { if (e.key === 'ArrowDown') { e.preventDefault() setSelectedIndex(i => Math.min(i + 1, results.length - 1)) } else if (e.key === 'ArrowUp') { e.preventDefault() setSelectedIndex(i => Math.max(i - 1, 0)) } else if (e.key === 'Enter') { e.preventDefault() if (results[selectedIndex]) { onSelect(results[selectedIndex]) } } else if (e.key === 'Escape') { e.preventDefault() onClose() } }, [results, selectedIndex, onSelect, onClose]) useEffect(() => { window.addEventListener('keydown', handleKeyDown) return () => window.removeEventListener('keydown', handleKeyDown) }, [handleKeyDown]) if (results.length === 0) return null return (
{t('agent.commands')}
{results.map((cmd, i) => ( ))}
) }