diff --git a/src/views/inputArea.ts b/src/views/inputArea.ts index 1665e5f..bdc3bbe 100644 --- a/src/views/inputArea.ts +++ b/src/views/inputArea.ts @@ -1,4 +1,9 @@ import { getWaveformPreviewContent } from "./waveformPreviewContent"; +import { + getModelSelectorContent, + getModelSelectorStyles, + getModelSelectorScript +} from "./modelSelector"; /** * 获取输入区域的 HTML 内容 @@ -54,24 +59,7 @@ export function getInputAreaContent(): string { 切换模式 - -
-
-
- Auto - - - -
-
-
Lite
-
Auto
-
Syntaxic
-
Max
-
-
- 选择模型 -
+ ${getModelSelectorContent()}
@@ -132,6 +120,7 @@ export function getInputAreaContent(): string { */ export function getInputAreaStyles(): string { return ` + ${getModelSelectorStyles()} .input-area { border-top: 1px solid var(--vscode-panel-border); padding-top: 15px; @@ -256,7 +245,7 @@ export function getInputAreaStyles(): string { gap: 8px; position: relative; } - /* 自定义下拉框样式 */ + /* 自定义下拉框样式(用于模式选择) */ .custom-select { position: relative; user-select: none; @@ -305,17 +294,18 @@ export function getInputAreaStyles(): string { .custom-select.active .select-dropdown { display: block; } - .select-option { + /* 模式选择器的选项样式 */ + #selectDropdown .select-option { padding: 6px 12px; font-size: 12px; cursor: pointer; transition: background 0.2s ease; white-space: nowrap; } - .select-option:hover { + #selectDropdown .select-option:hover { background: rgba(128, 128, 128, 0.3); } - .select-option.selected { + #selectDropdown .select-option.selected { background: rgba(128, 128, 128, 0.5); color: var(--vscode-foreground); } @@ -571,6 +561,8 @@ export function getInputAreaStyles(): string { */ export function getInputAreaScript(): string { return ` + ${getModelSelectorScript()} + // 自动调整 textarea 高度 function autoResizeTextarea() { if (messageInput) { @@ -592,7 +584,6 @@ export function getInputAreaScript(): string { // 自定义下拉框相关变量 let currentMode = 'agent'; - let currentModel = 'auto'; // 切换模式下拉框显示/隐藏 function toggleModeDropdown() { @@ -607,19 +598,6 @@ export function getInputAreaScript(): string { } } - // 切换模型下拉框显示/隐藏 - function toggleModelDropdown() { - const modelSelect = document.getElementById('modelSelect'); - const customSelect = document.getElementById('customSelect'); - if (modelSelect) { - modelSelect.classList.toggle('active'); - // 关闭模式下拉框 - if (customSelect) { - customSelect.classList.remove('active'); - } - } - } - // 选择模式 function selectMode(value, label) { currentMode = value; @@ -645,43 +623,13 @@ export function getInputAreaScript(): string { } } - // 选择模型 - function selectModel(value, label) { - currentModel = value; - const modelValue = document.getElementById('modelValue'); - if (modelValue) { - modelValue.textContent = label; - } - - // 更新选中状态 - const options = document.querySelectorAll('#modelDropdown .select-option'); - options.forEach(option => { - if (option.getAttribute('data-value') === value) { - option.classList.add('selected'); - } else { - option.classList.remove('selected'); - } - }); - - // 关闭下拉框 - const modelSelect = document.getElementById('modelSelect'); - if (modelSelect) { - modelSelect.classList.remove('active'); - } - } - // 点击外部关闭下拉框 document.addEventListener('click', (event) => { const customSelect = document.getElementById('customSelect'); - const modelSelect = document.getElementById('modelSelect'); if (customSelect && !customSelect.contains(event.target)) { customSelect.classList.remove('active'); } - - if (modelSelect && !modelSelect.contains(event.target)) { - modelSelect.classList.remove('active'); - } }); function sendMessage() { @@ -689,7 +637,7 @@ export function getInputAreaScript(): string { if (!text) return; const mode = currentMode; - const model = currentModel; + const model = getCurrentModel(); // 从模型选择器组件获取当前模型 addMessage(text, 'user'); vscode.postMessage({ command: 'sendMessage', text: text, mode: mode, model: model }); diff --git a/src/views/modelSelector.ts b/src/views/modelSelector.ts new file mode 100644 index 0000000..698ce00 --- /dev/null +++ b/src/views/modelSelector.ts @@ -0,0 +1,250 @@ +/** + * 模型选择器组件 + */ + +/** + * 获取模型选择器的 HTML 内容 + */ +export function getModelSelectorContent(): string { + return ` + +
+
+
+ Auto + + + +
+
+
Lite
+
Auto
+
Syntaxic
+
Max
+
+ +
+
+ 选择模型 +
+ `; +} + +/** + * 获取模型选择器的样式 + */ +export function getModelSelectorStyles(): string { + return ` + /* 自定义下拉框样式 */ + .custom-select { + position: relative; + user-select: none; + } + .select-trigger { + display: flex; + align-items: center; + gap: 6px; + padding: 4px 8px; + background: var(--vscode-input-background); + color: var(--vscode-foreground); + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 12px; + transition: background 0.2s ease; + } + .select-trigger:hover { + background: var(--vscode-list-hoverBackground); + } + .select-value { + white-space: nowrap; + } + .select-arrow { + width: 12px; + height: 12px; + flex-shrink: 0; + transition: transform 0.2s ease; + } + .custom-select.active .select-arrow { + transform: rotate(180deg); + } + .select-dropdown { + position: absolute; + bottom: calc(100% + 2px); + left: 0; + min-width: 100%; + background: var(--vscode-dropdown-background); + border: 1px solid var(--vscode-dropdown-border); + border-radius: 4px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + z-index: 1100; + display: none; + overflow: visible; + } + .custom-select.active .select-dropdown { + display: block; + } + /* 模型选择器的选项样式 */ + #modelDropdown .select-option { + position: relative; + padding: 6px 12px; + font-size: 12px; + cursor: pointer; + transition: background 0.2s ease; + white-space: nowrap; + } + #modelDropdown .select-option:hover { + background: rgba(128, 128, 128, 0.3); + } + #modelDropdown .select-option.selected { + background: rgba(128, 128, 128, 0.5); + color: var(--vscode-foreground); + } + /* 模型选择器的 tooltip 样式 */ + .model-tooltip { + position: fixed; + background: #1e1e1e; + color: #ffffff; + padding: 8px 12px; + border-radius: 6px; + font-size: 12px; + white-space: nowrap; + pointer-events: none; + z-index: 10000; + border: 1px solid rgba(255, 255, 255, 0.2); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6); + opacity: 0; + visibility: hidden; + transition: opacity 0.2s ease, visibility 0.2s ease; + } + .model-tooltip.show { + opacity: 1; + visibility: visible; + } + /* tooltip 箭头 */ + .model-tooltip::before { + content: ""; + position: absolute; + right: 100%; + top: 50%; + transform: translateY(-50%); + border-width: 7px; + border-style: solid; + border-color: transparent rgba(255, 255, 255, 0.2) transparent transparent; + z-index: -1; + } + .model-tooltip::after { + content: ""; + position: absolute; + right: 100%; + top: 50%; + transform: translateY(-50%); + border-width: 6px; + border-style: solid; + border-color: transparent #1e1e1e transparent transparent; + margin-right: 1px; + } + `; +} + +/** + * 获取模型选择器的脚本 + */ +export function getModelSelectorScript(): string { + return ` + // 模型选择相关变量 + let currentModel = 'auto'; + + // 切换模型下拉框显示/隐藏 + function toggleModelDropdown() { + const modelSelect = document.getElementById('modelSelect'); + const customSelect = document.getElementById('customSelect'); + if (modelSelect) { + modelSelect.classList.toggle('active'); + // 关闭模式下拉框 + if (customSelect) { + customSelect.classList.remove('active'); + } + } + } + + // 选择模型 + function selectModel(value, label) { + currentModel = value; + const modelValue = document.getElementById('modelValue'); + if (modelValue) { + modelValue.textContent = label; + } + + // 更新选中状态 + const options = document.querySelectorAll('#modelDropdown .select-option'); + options.forEach(option => { + if (option.getAttribute('data-value') === value) { + option.classList.add('selected'); + } else { + option.classList.remove('selected'); + } + }); + + // 关闭下拉框 + const modelSelect = document.getElementById('modelSelect'); + if (modelSelect) { + modelSelect.classList.remove('active'); + } + } + + // 点击外部关闭模型下拉框 + document.addEventListener('click', (event) => { + const modelSelect = document.getElementById('modelSelect'); + if (modelSelect && !modelSelect.contains(event.target)) { + modelSelect.classList.remove('active'); + } + }); + + // 获取当前选中的模型 + function getCurrentModel() { + return currentModel; + } + + // 模型选择器 tooltip 功能 + (function initModelTooltip() { + const modelDropdown = document.getElementById('modelDropdown'); + const modelTooltip = document.getElementById('modelTooltip'); + + if (!modelDropdown || !modelTooltip) return; + + // 为每个选项添加鼠标事件 + const options = modelDropdown.querySelectorAll('.select-option'); + + options.forEach(option => { + option.addEventListener('mouseenter', function(e) { + const tooltipText = this.getAttribute('data-tooltip'); + if (!tooltipText) return; + + // 设置 tooltip 内容 + modelTooltip.textContent = tooltipText; + + // 获取选项的位置 + const rect = this.getBoundingClientRect(); + + // 计算 tooltip 位置(在选项右侧) + const tooltipRect = modelTooltip.getBoundingClientRect(); + const left = rect.right + 12; + const top = rect.top + (rect.height / 2) - (tooltipRect.height / 2); + + // 设置位置 + modelTooltip.style.left = left + 'px'; + modelTooltip.style.top = top + 'px'; + + // 显示 tooltip + modelTooltip.classList.add('show'); + }); + + option.addEventListener('mouseleave', function() { + // 隐藏 tooltip + modelTooltip.classList.remove('show'); + }); + }); + })(); + `; +}