style: 移除Python文件中的编码声明并优化代码格式

refactor: 重构前端组件和样式,添加AI助手功能

docs: 更新README文档,添加ruff代码检查说明

feat: 新增AI助手相关API和前端组件

chore: 更新.gitignore文件,添加ruff缓存配置

fix: 修复前端布局和设置相关的问题

perf: 优化代码结构和性能,移除冗余代码

test: 更新测试文件,移除编码声明

build: 更新依赖版本,调整requirements.txt
This commit is contained in:
zhangtao
2026-01-16 01:13:59 +08:00
parent 59c1ce1104
commit d50dd9dd1e
210 changed files with 5236 additions and 4037 deletions
+255
View File
@@ -0,0 +1,255 @@
import { useRoute } from "vue-router";
import { ElMessage, ElMessageBox } from "element-plus";
import { onMounted, onBeforeUnmount, nextTick } from "vue";
import McpAPI from "@/api/module_application/mcp";
/**
* AI 操作处理器(简化版)
*
* 可以是简单函数,也可以是配置对象
*/
export type AiActionHandler<T = any> =
| ((args: T) => Promise<void> | void)
| {
/** 执行函数 */
execute: (args: T) => Promise<void> | void;
/** 是否需要确认(默认 true) */
needConfirm?: boolean;
/** 确认消息(支持函数或字符串) */
confirmMessage?: string | ((args: T) => string);
/** 成功消息(支持函数或字符串) */
successMessage?: string | ((args: T) => string);
/** 是否调用后端 API(默认 false,如果为 true 则自动调用 executeCommand) */
callBackendApi?: boolean;
};
/**
* AI 操作配置
*/
export interface UseAiActionOptions {
/** 操作映射表:函数名 -> 处理器 */
actionHandlers?: Record<string, AiActionHandler>;
/** 数据刷新函数(操作完成后调用) */
onRefresh?: () => Promise<void> | void;
/** 自动搜索处理函数 */
onAutoSearch?: (keywords: string) => void;
/** 当前路由路径(用于执行命令时传递) */
currentRoute?: string;
}
/**
* AI 操作 Composable
*
* 统一处理 AI 助手传递的操作,支持:
* - 自动搜索(通过 keywords + autoSearch 参数)
* - 执行 AI 操作(通过 aiAction 参数)
* - 配置化的操作处理器
*/
export function useAiAction(options: UseAiActionOptions = {}) {
const route = useRoute();
const { actionHandlers = {}, onRefresh, onAutoSearch, currentRoute = route.path } = options;
// 用于跟踪是否已卸载,防止在卸载后执行回调
let isUnmounted = false;
/**
* 执行 AI 操作(统一处理确认、执行、反馈流程)
*/
async function executeAiAction(action: any) {
if (isUnmounted) return;
// 兼容两种入参:{ functionName, arguments } 或 { functionCall: { name, arguments } }
const fnCall = action.functionCall ?? {
name: action.functionName,
arguments: action.arguments,
};
if (!fnCall?.name) {
ElMessage.warning("未识别的 AI 操作");
return;
}
// 查找对应的处理器
const handler = actionHandlers[fnCall.name];
if (!handler) {
ElMessage.warning(`暂不支持操作: ${fnCall.name}`);
return;
}
try {
// 判断处理器类型(函数 or 配置对象)
const isSimpleFunction = typeof handler === "function";
if (isSimpleFunction) {
// 简单函数形式:直接执行
await handler(fnCall.arguments);
} else {
// 配置对象形式:统一处理确认、执行、反馈
const config = handler;
// 1. 确认阶段(默认需要确认)
if (config.needConfirm !== false) {
const confirmMsg =
typeof config.confirmMessage === "function"
? config.confirmMessage(fnCall.arguments)
: config.confirmMessage || "确认执行此操作吗?";
await ElMessageBox.confirm(confirmMsg, "AI 助手操作确认", {
confirmButtonText: "确认执行",
cancelButtonText: "取消",
type: "warning",
dangerouslyUseHTMLString: true,
});
}
// 2. 执行阶段
if (config.callBackendApi) {
// 自动调用后端 API
await McpAPI.chatMcp({
message: fnCall.arguments,
});
} else {
// 执行自定义函数
await config.execute(fnCall.arguments);
}
// 3. 成功反馈
const successMsg =
typeof config.successMessage === "function"
? config.successMessage(fnCall.arguments)
: config.successMessage || "操作执行成功";
ElMessage.success(successMsg);
}
// 4. 刷新数据
if (onRefresh) {
await onRefresh();
}
} catch (error: any) {
// 处理取消操作
if (error === "cancel") {
ElMessage.info("已取消操作");
return;
}
console.error("AI 操作执行失败:", error);
ElMessage.error(error.message || "操作执行失败");
}
}
/**
* 执行后端命令(通用方法)
*/
async function executeCommand(
functionName: string,
args: any,
options: {
originalCommand?: string;
confirmMode?: "auto" | "manual";
needConfirm?: boolean;
confirmMessage?: string;
} = {}
) {
const {
originalCommand = "",
confirmMode = "manual",
needConfirm = false,
confirmMessage,
} = options;
// 如果需要确认,先显示确认对话框
if (needConfirm && confirmMessage) {
try {
await ElMessageBox.confirm(confirmMessage, "AI 助手操作确认", {
confirmButtonText: "确认执行",
cancelButtonText: "取消",
type: "warning",
dangerouslyUseHTMLString: true,
});
} catch {
ElMessage.info("已取消操作");
return;
}
}
try {
await McpAPI.chatMcp({
message: originalCommand,
});
ElMessage.success("操作执行成功");
} catch (error: any) {
if (error !== "cancel") {
throw error;
}
}
}
/**
* 处理自动搜索
*/
function handleAutoSearch(keywords: string) {
if (onAutoSearch) {
onAutoSearch(keywords);
} else {
ElMessage.info(`AI 助手已为您自动搜索:${keywords}`);
}
}
/**
* 初始化:处理 URL 参数中的 AI 操作
*
* 注意:此方法只处理 AI 相关参数,不负责页面数据的初始加载
* 页面数据加载应由组件的 onMounted 钩子自行处理
*/
async function init() {
if (isUnmounted) return;
// 检查是否有 AI 助手传递的参数
const keywords = route.query.keywords as string;
const autoSearch = route.query.autoSearch as string;
const aiActionParam = route.query.aiAction as string;
// 如果没有任何 AI 参数,直接返回
if (!keywords && !autoSearch && !aiActionParam) {
return;
}
// 在 nextTick 中执行,确保页面数据已加载
nextTick(async () => {
if (isUnmounted) return;
// 1. 处理自动搜索
if (autoSearch === "true" && keywords) {
handleAutoSearch(keywords);
}
// 2. 处理 AI 操作
if (aiActionParam) {
try {
const aiAction = JSON.parse(decodeURIComponent(aiActionParam));
await executeAiAction(aiAction);
} catch (error) {
console.error("解析 AI 操作失败:", error);
ElMessage.error("AI 操作参数解析失败");
}
}
});
}
// 组件挂载时自动初始化
onMounted(() => {
init();
});
// 组件卸载时清理
onBeforeUnmount(() => {
isUnmounted = true;
});
return {
executeAiAction,
executeCommand,
handleAutoSearch,
};
}
+3
View File
@@ -1 +1,4 @@
// 该文件作用是:导出所有 composable 函数,作为全局函数使用
// AI 相关
export { useAiAction } from "./ai/useAiAction";
export type { UseAiActionOptions, AiActionHandler } from "./ai/useAiAction";