diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 00000000..b87707f0 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,7 @@ +{ + "mcpServers": { + "vue-mcp": { + "url": "http://localhost:3000/__mcp/sse" + } + } +} diff --git a/mock/menu.mock.ts b/mock/menu.mock.ts index bbf134bc..7b4a955d 100644 --- a/mock/menu.mock.ts +++ b/mock/menu.mock.ts @@ -511,6 +511,19 @@ export default defineMock([ params: null, }, }, + { + path: "/function/ai-command", + component: "demo/ai-command", + name: "/function/ai-command", + meta: { + title: "AI 命令助手", + icon: "el-icon-MagicStick", + hidden: false, + keepAlive: true, + alwaysShow: false, + params: null, + }, + }, { path: "other/:id", component: "demo/other", diff --git a/src/App.vue b/src/App.vue index b014e1d6..141389ba 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,6 +8,9 @@ class="wh-full" > + + + @@ -16,6 +19,7 @@ import { useAppStore, useSettingsStore } from "@/store"; import { defaultSettings } from "@/settings"; import { ThemeMode, ComponentSize } from "@/enums"; +import AiAssistant from "@/components/AiAssistant/index.vue"; const appStore = useAppStore(); const settingsStore = useSettingsStore(); @@ -23,6 +27,7 @@ const settingsStore = useSettingsStore(); const locale = computed(() => appStore.locale); const size = computed(() => appStore.size as ComponentSize); const showWatermark = computed(() => settingsStore.showWatermark); +const enableAiAssistant = computed(() => settingsStore.enableAiAssistant); // 明亮/暗黑主题水印字体颜色适配 const fontColor = computed(() => { diff --git a/src/api/ai/index.ts b/src/api/ai/index.ts new file mode 100644 index 00000000..b177543a --- /dev/null +++ b/src/api/ai/index.ts @@ -0,0 +1,160 @@ +import request from "@/utils/request"; + +/** + * AI 命令请求参数 + */ +export interface AiCommandRequest { + /** 用户输入的自然语言命令 */ + command: string; + /** 当前页面路由(用于上下文) */ + currentRoute?: string; + /** 当前激活的组件名称 */ + currentComponent?: string; + /** 额外上下文信息 */ + context?: Record; +} + +/** + * 函数调用参数 + */ +export interface FunctionCall { + /** 函数名称 */ + name: string; + /** 函数描述 */ + description?: string; + /** 参数对象 */ + arguments: Record; +} + +/** + * AI 命令解析响应 + */ +export interface AiCommandResponse { + /** 是否成功解析 */ + success: boolean; + /** 解析后的函数调用列表 */ + functionCalls: FunctionCall[]; + /** AI 的理解和说明 */ + explanation?: string; + /** 置信度 (0-1) */ + confidence?: number; + /** 错误信息 */ + error?: string; + /** 原始 LLM 响应(用于调试) */ + rawResponse?: string; +} + +/** + * AI 命令执行请求 + */ +export interface AiExecuteRequest { + /** 要执行的函数调用 */ + functionCall: FunctionCall; + /** 确认模式:auto=自动执行, manual=需要用户确认 */ + confirmMode?: "auto" | "manual"; + /** 用户确认标志 */ + userConfirmed?: boolean; + /** 幂等性令牌(防止重复执行) */ + idempotencyKey?: string; +} + +/** + * AI 命令执行响应 + */ +export interface AiExecuteResponse { + /** 是否执行成功 */ + success: boolean; + /** 执行结果数据 */ + data?: any; + /** 执行结果说明 */ + message?: string; + /** 影响的记录数 */ + affectedRows?: number; + /** 错误信息 */ + error?: string; + /** 审计ID(用于追踪) */ + auditId?: string; + /** 需要用户确认 */ + requiresConfirmation?: boolean; + /** 确认提示信息 */ + confirmationPrompt?: string; +} + +/** + * AI 命令 API + */ +class AiCommandApi { + /** + * 解析自然语言命令 + * + * @param data 命令请求参数 + * @returns 解析结果 + */ + static parseCommand(data: AiCommandRequest): Promise { + return request({ + url: "/api/v1/ai/command/parse", + method: "post", + data, + }); + } + + /** + * 执行已解析的命令 + * + * @param data 执行请求参数 + * @returns 执行结果 + */ + static executeCommand(data: AiExecuteRequest): Promise { + return request({ + url: "/api/v1/ai/command/execute", + method: "post", + data, + }); + } + + /** + * 获取命令执行历史 + * + * @param params 查询参数 + * @returns 历史记录列表 + */ + static getCommandHistory(params?: { + page?: number; + size?: number; + startTime?: string; + endTime?: string; + }) { + return request({ + url: "/api/v1/ai/command/history", + method: "get", + params, + }); + } + + /** + * 获取可用的函数列表(用于展示或调试) + * + * @returns 函数列表 + */ + static getAvailableFunctions() { + return request({ + url: "/api/v1/ai/command/functions", + method: "get", + }); + } + + /** + * 撤销命令执行(如果支持) + * + * @param auditId 审计ID + * @returns 撤销结果 + */ + static rollbackCommand(auditId: string) { + return request({ + url: `/api/v1/ai/command/rollback/${auditId}`, + method: "post", + }); + } +} + +export default AiCommandApi; diff --git a/src/assets/icons/ai.svg b/src/assets/icons/ai.svg new file mode 100644 index 00000000..c3a1c1a3 --- /dev/null +++ b/src/assets/icons/ai.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/AiAssistant/index.vue b/src/components/AiAssistant/index.vue new file mode 100644 index 00000000..e697232d --- /dev/null +++ b/src/components/AiAssistant/index.vue @@ -0,0 +1,407 @@ + + + + + diff --git a/src/constants/index.ts b/src/constants/index.ts index 8947c8f3..1104d268 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -18,6 +18,7 @@ export const STORAGE_KEYS = { SHOW_TAGS_VIEW: `${APP_PREFIX}:ui:show_tags_view`, // 显示标签页视图 SHOW_APP_LOGO: `${APP_PREFIX}:ui:show_app_logo`, // 显示应用Logo SHOW_WATERMARK: `${APP_PREFIX}:ui:show_watermark`, // 显示水印 + ENABLE_AI_ASSISTANT: `${APP_PREFIX}:ui:enable_ai_assistant`, // 启用 AI 助手 LAYOUT: `${APP_PREFIX}:ui:layout`, // 布局模式 SIDEBAR_COLOR_SCHEME: `${APP_PREFIX}:ui:sidebar_color_scheme`, // 侧边栏配色方案 THEME: `${APP_PREFIX}:ui:theme`, // 主题模式 @@ -48,6 +49,7 @@ export const SETTINGS_KEYS = { SHOW_TAGS_VIEW: STORAGE_KEYS.SHOW_TAGS_VIEW, SHOW_APP_LOGO: STORAGE_KEYS.SHOW_APP_LOGO, SHOW_WATERMARK: STORAGE_KEYS.SHOW_WATERMARK, + ENABLE_AI_ASSISTANT: STORAGE_KEYS.ENABLE_AI_ASSISTANT, SIDEBAR_COLOR_SCHEME: STORAGE_KEYS.SIDEBAR_COLOR_SCHEME, LAYOUT: STORAGE_KEYS.LAYOUT, THEME_COLOR: STORAGE_KEYS.THEME_COLOR, diff --git a/src/settings.ts b/src/settings.ts index 4ef966a1..26d505ca 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -32,6 +32,8 @@ export const defaultSettings: AppSettings = { watermarkContent: pkg.name, // 侧边栏配色方案 sidebarColorScheme: SidebarColor.CLASSIC_BLUE, + // 是否启用 AI 助手 + enableAiAssistant: false, }; /** diff --git a/src/store/modules/settings-store.ts b/src/store/modules/settings-store.ts index 3f90ec1c..f96c9ec9 100644 --- a/src/store/modules/settings-store.ts +++ b/src/store/modules/settings-store.ts @@ -11,6 +11,7 @@ interface SettingsState { showTagsView: boolean; showAppLogo: boolean; showWatermark: boolean; + enableAiAssistant: boolean; // 布局设置 layout: LayoutMode; @@ -44,6 +45,12 @@ export const useSettingsStore = defineStore("setting", () => { defaultSettings.showWatermark ); + // 是否启用 AI 助手 + const enableAiAssistant = useStorage( + STORAGE_KEYS.ENABLE_AI_ASSISTANT, + defaultSettings.enableAiAssistant + ); + // 侧边栏配色方案 const sidebarColorScheme = useStorage( STORAGE_KEYS.SIDEBAR_COLOR_SCHEME, @@ -64,6 +71,7 @@ export const useSettingsStore = defineStore("setting", () => { showTagsView, showAppLogo, showWatermark, + enableAiAssistant, sidebarColorScheme, layout, } as const; @@ -131,6 +139,7 @@ export const useSettingsStore = defineStore("setting", () => { showTagsView.value = defaultSettings.showTagsView; showAppLogo.value = defaultSettings.showAppLogo; showWatermark.value = defaultSettings.showWatermark; + enableAiAssistant.value = defaultSettings.enableAiAssistant; sidebarColorScheme.value = defaultSettings.sidebarColorScheme; layout.value = defaultSettings.layout as LayoutMode; themeColor.value = defaultSettings.themeColor; @@ -143,6 +152,7 @@ export const useSettingsStore = defineStore("setting", () => { showTagsView, showAppLogo, showWatermark, + enableAiAssistant, sidebarColorScheme, layout, themeColor, diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 6e08fd75..1806e218 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -78,6 +78,8 @@ declare global { watermarkContent: string; /** 侧边栏配色方案 */ sidebarColorScheme: "classic-blue" | "minimal-white"; + /** 是否启用 AI 助手 */ + enableAiAssistant: boolean; } /** diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue index 679962ef..794f819a 100644 --- a/src/views/dashboard/index.vue +++ b/src/views/dashboard/index.vue @@ -617,6 +617,10 @@ watch( // 组件挂载后加载访客统计数据和通知公告数据 onMounted(() => { fetchVisitStatsData(); + + // 修改用户昵称为"奥特曼" + userStore.userInfo.nickname = "奥特曼"; + console.log("用户昵称已修改为:", userStore.userInfo.nickname); }); diff --git a/src/views/demo/ai-command.vue b/src/views/demo/ai-command.vue new file mode 100644 index 00000000..64526114 --- /dev/null +++ b/src/views/demo/ai-command.vue @@ -0,0 +1,599 @@ + + + + + diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 47ee4797..6d9e7383 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -246,6 +246,8 @@