import { getWaveformPreviewContent } from "./waveformPreviewContent"; import { getModelSelectorContent, getModelSelectorStyles, getModelSelectorScript, } from "./modelSelector"; import { getModeSelectorContent, getModeSelectorStyles, getModeSelectorScript, } from "./agentModeSelector"; import { getContextButtonContent, getContextButtonStyles, getContextButtonScript, } from "./contextButton"; import { getContextCompressContent, getContextCompressStyles, getContextCompressScript, } from "./contextCompress"; import { getOptimizeButtonContent, getOptimizeButtonStyles, getOptimizeButtonScript, } from "./optimizeButton"; import { sendIconSvg, stopIconSvg } from "../constants/toolIcons"; /** * 获取输入区域的 HTML 内容 */ export function getInputAreaContent( autoIcon: string = '', liteIcon: string = '', syIcon: string = '', maxIcon: string = '' ): string { return `
${getContextButtonContent()}
${getModeSelectorContent()} ${getModelSelectorContent(autoIcon, liteIcon, syIcon, maxIcon)}
${getContextCompressContent()} ${getOptimizeButtonContent()}
`; } /** * 获取输入区域的样式 */ export function getInputAreaStyles(): string { return ` ${getModeSelectorStyles()} ${getModelSelectorStyles()} ${getContextButtonStyles()} ${getContextCompressStyles()} ${getOptimizeButtonStyles()} .input-area { border-top: 1px solid var(--vscode-panel-border); padding-top: 15px; flex-shrink: 0; } .input-group { display: flex; flex-direction: column; gap: 10px; background: var(--vscode-input-background); border: 1px solid var(--vscode-input-border); border-radius: 8px; padding: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15), 0 2px 6px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; } .input-group:hover { box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2), 0 3px 8px rgba(0, 0, 0, 0.15); } .input-group:focus-within { border-color: var(--vscode-focusBorder); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25), 0 3px 10px rgba(0, 0, 0, 0.2); } .input-wrapper { display: flex; flex-direction: column; gap: 8px; width: 100%; } /* 顶部工具栏样式 */ .input-top-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; gap: 12px; } .input-bottom-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: -17px; } .mode-selector { display: flex; align-items: center; gap: 8px; position: relative; } .input-actions { display: flex; align-items: center; gap: 10px; } /* Tooltip 样式 */ .tooltip { position: relative; display: inline-block; } .tooltip .tooltiptext { visibility: hidden; width: auto; background: #1e1e1e; color: #ffffff; text-align: center; border-radius: 6px; padding: 6px 12px; position: absolute; z-index: 1000; bottom: 150%; left: 50%; transform: translateX(-50%) translateY(10px); opacity: 0; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); font-size: 12px; font-weight: 500; border: 1px solid rgba(255, 255, 255, 0.2); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.3); white-space: nowrap; letter-spacing: 0.3px; } .tooltip .tooltiptext::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -6px; border-width: 6px; border-style: solid; border-color: #1e1e1e transparent transparent transparent; } .tooltip .tooltiptext::before { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -7px; border-width: 7px; border-style: solid; border-color: rgba(255, 255, 255, 0.2) transparent transparent transparent; z-index: -1; } .tooltip:hover .tooltiptext { visibility: visible; opacity: 1; transform: translateX(-50%) translateY(0); } textarea { width: 100%; padding: 10px; background: transparent; color: var(--vscode-input-foreground); border: none; border-radius: 4px; font-family: inherit; resize: none; min-height: 40px; max-height: 200px; outline: none; box-sizing: border-box; overflow-y: auto; line-height: 1.5; } textarea:disabled { opacity: 0.5; cursor: not-allowed; background: rgba(128, 128, 128, 0.1); } /* 简洁的滚动条样式 */ textarea::-webkit-scrollbar { width: 8px; } textarea::-webkit-scrollbar-track { background: transparent; } textarea::-webkit-scrollbar-thumb { background: rgba(128, 128, 128, 0.5); border-radius: 4px; } textarea::-webkit-scrollbar-button { display: none; } button { padding: 0 20px; background: var(--vscode-button-background); color: var(--vscode-button-foreground); border: none; border-radius: 4px; cursor: pointer; transition: background 0.2s ease; display: flex; align-items: center; justify-content: center; } button:hover { background: var(--vscode-button-hoverBackground); } /* 发送按钮状态样式 */ #sendButton { position: relative; min-width: 32px; padding: 6px 8px; } #sendButton svg { width: 14px; height: 14px; display: block; } #sendButton.sending { background: var(--vscode-button-background); } #sendButton.sending:hover { background: var(--vscode-button-hoverBackground); } `; } /** * 获取输入区域的脚本 */ export function getInputAreaScript(): string { return ` // 注意:getModeSelectorScript() 已在 webviewContent.ts 开头加载,这里不再重复加载 ${getModelSelectorScript()} ${getContextButtonScript()} ${getContextCompressScript()} ${getOptimizeButtonScript()} // 对话状态管理 let isConversationActive = false; // 工作区检测状态 let hasCheckedWorkspace = false; // 是否已经检测过工作区 let hasWorkspace = true; // 工作区状态 // 自动调整 textarea 高度 function autoResizeTextarea() { if (messageInput) { messageInput.style.height = 'auto'; messageInput.style.height = messageInput.scrollHeight + 'px'; } } // 监听输入事件,自动调整高度 if (messageInput) { messageInput.addEventListener('input', autoResizeTextarea); // 监听点击事件,检测工作区状态 messageInput.addEventListener('focus', () => { if (!hasCheckedWorkspace) { hasCheckedWorkspace = true; vscode.postMessage({ command: 'checkWorkspace' }); } }); // 初始化时调整一次高度 autoResizeTextarea(); } // 切换发送按钮状态 function setSendButtonState(isSending) { const sendButton = document.getElementById('sendButton'); const children = sendButton.children; const sendIconContainer = children[0]; // 第一个子元素是发送图标的 SVG const stopIconContainer = children[1]; // 第二个子元素是包含暂停图标的 span if (isSending) { sendButton.classList.add('sending'); sendIconContainer.style.display = 'none'; stopIconContainer.style.display = 'block'; isConversationActive = true; // 禁用输入框 messageInput.disabled = true; messageInput.placeholder = '正在处理中,请稍候...'; } else { sendButton.classList.remove('sending'); sendIconContainer.style.display = 'block'; stopIconContainer.style.display = 'none'; isConversationActive = false; // 启用输入框 messageInput.disabled = false; messageInput.placeholder = '输入您的问题,按 Enter 发送,Shift + Enter 换行...'; } } // 处理发送或停止 function handleSendOrStop() { if (isConversationActive) { // 当前正在对话,执行停止操作 vscode.postMessage({ command: 'abortDialog' }); setSendButtonState(false); } else { // 当前未在对话,执行发送操作 sendMessage(); } } function sendMessage() { const text = messageInput.value.trim(); if (!text) return; // 如果正在对话中,阻止发送新消息 if (isConversationActive) { return; } // 检查工作区状态 if (!hasWorkspace) { // 如果没有工作区,阻止发送并清空输入框 messageInput.value = ''; autoResizeTextarea(); return; } const mode = getCurrentMode(); // 从模式选择器组件获取当前模式 const model = getCurrentModel(); // 从模型选择器组件获取当前模型 const planMode = document.getElementById('planToggle')?.checked || false; addMessage(text, 'user'); // 切换按钮为暂停状态 setSendButtonState(true); vscode.postMessage({ command: 'sendMessage', text: text, mode: mode, model: model, planMode: planMode }); messageInput.value = ''; autoResizeTextarea(); // 重置输入框高度 messageInput.focus(); // 重置优化状态 resetOptimizeButton(); } `; }