diff --git a/src-tauri/src/filesystem.rs b/src-tauri/src/filesystem.rs index d842aed6..4016702d 100644 --- a/src-tauri/src/filesystem.rs +++ b/src-tauri/src/filesystem.rs @@ -1766,7 +1766,10 @@ pub async fn git_hook_read(root: String, name: String) -> Result } /// 写入某钩子内容并按 executable 设置可执行权限(类 Unix)。 +/// executable 仅在类 Unix 平台使用;非 Unix 下显式 allow,避免 clippy -D warnings 失败 +/// (参数名需保持不变以匹配前端 Tauri 调用,故不能改名为 _executable)。 #[tauri::command] +#[cfg_attr(not(unix), allow(unused_variables))] pub async fn git_hook_save( root: String, name: String, diff --git a/src/App.vue b/src/App.vue index d015904c..93ef9f21 100644 --- a/src/App.vue +++ b/src/App.vue @@ -366,6 +366,10 @@ + + + @@ -414,6 +418,10 @@
+ + + +
@@ -503,6 +511,7 @@ import GitPanel from './components/GitPanel.vue' import TaskRunner from './components/TaskRunner.vue' import DebugToolbar from './components/DebugToolbar.vue' import DebugPanel from './components/DebugPanel.vue' +import AiCodeAction from './components/AiCodeAction.vue' import GoToLine from './components/GoToLine.vue' import Outline from './components/Outline.vue' import SnippetManager from './components/SnippetManager.vue' @@ -1260,6 +1269,44 @@ const runTests = async () => { await runTask(cmd) } +// C2:对选区(无选区则整篇)执行 AI 操作:解释 / 重构 / 生成测试 +const aiCodeCtx = ref<{action: 'explain' | 'refactor' | 'test'; code: string; from: number; to: number} | null>(null) +const aiCodeAction = (action: 'explain' | 'refactor' | 'test') => { + closeEditorCtx() + const view = editorView.value + if (!view) { + return + } + const sel = view.state.selection.main + let from = sel.from + let to = sel.to + let code = sel.empty ? '' : view.state.sliceDoc(from, to) + if (!code.trim()) { + code = view.state.doc.toString() + from = 0 + to = view.state.doc.length + } + if (!code.trim()) { + toast.info(t('aiCode.noCode')) + return + } + aiCodeCtx.value = {action, code, from, to} +} +const onAiReplace = (code: string) => { + const view = editorView.value + const ctx = aiCodeCtx.value + if (view && ctx) { + view.dispatch({changes: {from: ctx.from, to: ctx.to, insert: code}}) + } +} +const onAiInsert = (code: string) => { + const view = editorView.value + const ctx = aiCodeCtx.value + if (view && ctx) { + view.dispatch({changes: {from: ctx.to, insert: `\n\n${code}\n`}}) + } +} + // B3:发送选区(无选区则当前行)到集成终端,用于 REPL 式交互 const sendToTerminal = async () => { closeEditorCtx() diff --git a/src/components/AiAssistant.vue b/src/components/AiAssistant.vue index 9c8b3822..078eb92c 100644 --- a/src/components/AiAssistant.vue +++ b/src/components/AiAssistant.vue @@ -55,6 +55,20 @@ {{ t('chat.stop') }} + +
+ {{ t('chat.context') }} + + +