e0444a966f
- 新增系统命令模块 (core/system-commands) - 支持 :clear/:cls/:c 清空对话历史 - 命令注册表支持别名 - 可扩展的命令执行器 - Server 端支持 - 新增 /api/system-commands API - WebSocket 处理系统命令消息 - 会话清空 API 端点 - UI 端支持 - 新增 SystemCommandMenu 组件 - 输入 : 时显示命令建议菜单 - 键盘导航和选择 - 底部提示添加 : 快捷键
113 lines
2.7 KiB
TypeScript
113 lines
2.7 KiB
TypeScript
/**
|
|
* System Commands Hook
|
|
*
|
|
* 管理系统命令(: 前缀)的加载和过滤
|
|
*/
|
|
|
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
import { listSystemCommands } from '../api/client.js';
|
|
import type { SystemCommandInfo } from '../api/types.js';
|
|
|
|
interface UseSystemCommandsOptions {
|
|
/** 是否在挂载时自动加载命令列表 */
|
|
autoLoad?: boolean;
|
|
}
|
|
|
|
interface UseSystemCommandsState {
|
|
/** 所有系统命令列表 */
|
|
commands: SystemCommandInfo[];
|
|
/** 过滤后的命令列表 */
|
|
filteredCommands: SystemCommandInfo[];
|
|
/** 是否正在加载 */
|
|
isLoading: boolean;
|
|
/** 错误信息 */
|
|
error: string | null;
|
|
}
|
|
|
|
export function useSystemCommands(options: UseSystemCommandsOptions = {}) {
|
|
const { autoLoad = true } = options;
|
|
|
|
const [state, setState] = useState<UseSystemCommandsState>({
|
|
commands: [],
|
|
filteredCommands: [],
|
|
isLoading: false,
|
|
error: null,
|
|
});
|
|
|
|
const loadedRef = useRef(false);
|
|
|
|
// 加载系统命令列表
|
|
const loadCommands = useCallback(async () => {
|
|
if (state.isLoading) return;
|
|
|
|
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
|
|
try {
|
|
const result = await listSystemCommands();
|
|
if (result.success) {
|
|
setState({
|
|
commands: result.data.commands,
|
|
filteredCommands: result.data.commands,
|
|
isLoading: false,
|
|
error: null,
|
|
});
|
|
} else {
|
|
setState((prev) => ({
|
|
...prev,
|
|
isLoading: false,
|
|
error: 'Failed to load system commands',
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
setState((prev) => ({
|
|
...prev,
|
|
isLoading: false,
|
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
}));
|
|
}
|
|
}, [state.isLoading]);
|
|
|
|
// 搜索/过滤系统命令
|
|
const filterCommands = useCallback(
|
|
(query: string) => {
|
|
// 空查询显示所有命令
|
|
if (!query.trim()) {
|
|
setState((prev) => ({
|
|
...prev,
|
|
filteredCommands: prev.commands,
|
|
}));
|
|
return;
|
|
}
|
|
|
|
// 本地过滤
|
|
const queryLower = query.toLowerCase();
|
|
const localFiltered = state.commands.filter(
|
|
(cmd) =>
|
|
cmd.name.toLowerCase().includes(queryLower) ||
|
|
cmd.description?.toLowerCase().includes(queryLower) ||
|
|
cmd.aliases?.some((alias) => alias.toLowerCase().includes(queryLower))
|
|
);
|
|
|
|
setState((prev) => ({
|
|
...prev,
|
|
filteredCommands: localFiltered,
|
|
}));
|
|
},
|
|
[state.commands]
|
|
);
|
|
|
|
// 自动加载
|
|
useEffect(() => {
|
|
if (autoLoad && !loadedRef.current) {
|
|
loadedRef.current = true;
|
|
loadCommands();
|
|
}
|
|
}, [autoLoad, loadCommands]);
|
|
|
|
return {
|
|
...state,
|
|
loadCommands,
|
|
filterCommands,
|
|
};
|
|
}
|