diff --git a/src/constants/toolIcons.ts b/src/constants/toolIcons.ts index f685412..36e486e 100644 --- a/src/constants/toolIcons.ts +++ b/src/constants/toolIcons.ts @@ -179,7 +179,7 @@ export const userQuestionIconSvg = ``; +export const userAvatarIconSvg = ``; /** * 更新阶段图标 SVG @@ -189,4 +189,9 @@ export const updateStageIconSvg = ``; +export const moreIconSvg = ``; + +/** + * 设置的图标svg + */ +export const setting = ``; diff --git a/src/views/conversationHistoryBar.ts b/src/views/conversationHistoryBar.ts index fb79ecd..5baa326 100644 --- a/src/views/conversationHistoryBar.ts +++ b/src/views/conversationHistoryBar.ts @@ -8,7 +8,16 @@ import { getMoreOptionsComponentStyles, getMoreOptionsComponentScript, } from "./moreOptionsComponent"; -import { userAvatarIconSvg, moreIconSvg } from "../constants/toolIcons"; +import { + getSettingsComponentContent, + getSettingsComponentStyles, + getSettingsComponentScript, +} from "./settingsComponent"; +import { + userAvatarIconSvg, + moreIconSvg, + setting, +} from "../constants/toolIcons"; /** * 获取会话历史栏的 HTML 内容 @@ -45,6 +54,12 @@ export function getConversationHistoryBarContent(): string { ${getUserInfoComponentContent()} +
+ +
+
+ + ${getSettingsComponentContent()} `; } @@ -88,8 +105,8 @@ export function getConversationHistoryBarStyles(): string { } .user-avatar-icon-button { - width: 36px; - height: 36px; + width: 30px; + height: 30px; padding: 0; background: transparent; color: var(--vscode-foreground); @@ -123,13 +140,44 @@ export function getConversationHistoryBarStyles(): string { ${getUserInfoComponentStyles()} + ${getSettingsComponentStyles()} + + .setting { + position: relative; + } + + .setting-btn { + width: 30px; + height: 30px; + padding: 0; + background: transparent; + color: var(--vscode-foreground); + border: none; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + flex-shrink: 0; + } + + .setting-btn:hover { + background: var(--vscode-toolbar-hoverBackground); + transform: scale(1.1); + } + + .setting-btn:active { + transform: scale(0.95); + } + .more-container { position: relative; } .more-button { - width: 36px; - height: 36px; + width: 30px; + height: 30px; padding: 0; background: transparent; color: var(--vscode-foreground); @@ -266,8 +314,8 @@ export function getConversationHistoryBarStyles(): string { } .new-conversation-button { - width: 36px; - height: 36px; + width: 30px; + height: 30px; padding: 0; background: transparent; color: var(--vscode-foreground); @@ -324,6 +372,8 @@ export function getConversationHistoryBarScript(): string { ${getMoreOptionsComponentScript()} + ${getSettingsComponentScript()} + // 更新用户头像图标按钮显示 function updateUserAvatarIconButton(userInfo) { const userAvatarIconButton = document.getElementById('userAvatarIconButton'); diff --git a/src/views/generalSettingsComponent.ts b/src/views/generalSettingsComponent.ts new file mode 100644 index 0000000..caba8cf --- /dev/null +++ b/src/views/generalSettingsComponent.ts @@ -0,0 +1,327 @@ +/** + * 获取通用设置组件的 HTML 内容 + */ +export function getGeneralSettingsComponentContent(): string { + return ` +
+

通用设置

+ +
+
+
+ + 选择界面主题 +
+ +
+ +
+
+ + 选择界面语言 +
+ +
+ +
+
+ + 自动保存会话历史 +
+ +
+ +
+
+ + 在消息中显示时间戳 +
+ +
+
+ +
+

编辑器设置

+ +
+
+ + 设置编辑器字体大小 +
+ +
+ +
+
+ + 启用代码语法高亮 +
+ +
+
+ +
+ + +
+
+ `; +} + +/** + * 获取通用设置组件的 CSS 样式 + */ +export function getGeneralSettingsComponentStyles(): string { + return ` + .general-settings { + max-width: 600px; + } + + .settings-section-title { + margin: 0 0 20px 0; + font-size: 16px; + font-weight: 600; + color: var(--vscode-foreground); + } + + .settings-section { + margin-bottom: 32px; + } + + .settings-subsection-title { + margin: 0 0 16px 0; + font-size: 14px; + font-weight: 600; + color: var(--vscode-foreground); + opacity: 0.9; + } + + .settings-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 0; + border-bottom: 1px solid var(--vscode-panel-border); + } + + .settings-item:last-child { + border-bottom: none; + } + + .settings-item-header { + flex: 1; + display: flex; + flex-direction: column; + gap: 4px; + } + + .settings-item-label { + font-size: 14px; + font-weight: 500; + color: var(--vscode-foreground); + } + + .settings-item-description { + font-size: 12px; + color: var(--vscode-descriptionForeground); + } + + .settings-select { + padding: 6px 12px; + background: var(--vscode-input-background); + color: var(--vscode-input-foreground); + border: 1px solid var(--vscode-input-border); + border-radius: 4px; + font-size: 13px; + cursor: pointer; + outline: none; + } + + .settings-select:focus { + border-color: var(--vscode-focusBorder); + } + + .settings-input { + width: 80px; + padding: 6px 12px; + background: var(--vscode-input-background); + color: var(--vscode-input-foreground); + border: 1px solid var(--vscode-input-border); + border-radius: 4px; + font-size: 13px; + outline: none; + } + + .settings-input:focus { + border-color: var(--vscode-focusBorder); + } + + .settings-switch { + position: relative; + display: inline-block; + width: 44px; + height: 24px; + cursor: pointer; + } + + .settings-switch input { + opacity: 0; + width: 0; + height: 0; + } + + .settings-switch-slider { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--vscode-input-background); + border: 1px solid var(--vscode-input-border); + border-radius: 24px; + transition: all 0.3s ease; + } + + .settings-switch-slider:before { + content: ""; + position: absolute; + height: 16px; + width: 16px; + left: 3px; + bottom: 3px; + background: var(--vscode-foreground); + border-radius: 50%; + transition: all 0.3s ease; + } + + .settings-switch input:checked + .settings-switch-slider { + background: var(--vscode-button-background); + border-color: var(--vscode-button-background); + } + + .settings-switch input:checked + .settings-switch-slider:before { + transform: translateX(20px); + background: var(--vscode-button-foreground); + } + + .settings-actions { + display: flex; + gap: 12px; + margin-top: 24px; + padding-top: 24px; + border-top: 1px solid var(--vscode-panel-border); + } + + .settings-button { + padding: 8px 16px; + border: none; + border-radius: 4px; + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + } + + .settings-button-primary { + background: var(--vscode-button-background); + color: var(--vscode-button-foreground); + } + + .settings-button-primary:hover { + background: var(--vscode-button-hoverBackground); + } + + .settings-button-secondary { + background: var(--vscode-button-secondaryBackground); + color: var(--vscode-button-secondaryForeground); + } + + .settings-button-secondary:hover { + background: var(--vscode-button-secondaryHoverBackground); + } + `; +} + +/** + * 获取通用设置组件的 JavaScript 脚本 + */ +export function getGeneralSettingsComponentScript(): string { + return ` + // 保存通用设置 + function saveGeneralSettings() { + const settings = { + theme: document.getElementById('themeSelect').value, + language: document.getElementById('languageSelect').value, + autoSave: document.getElementById('autoSaveCheckbox').checked, + showTimestamp: document.getElementById('showTimestampCheckbox').checked, + fontSize: document.getElementById('fontSizeInput').value, + syntaxHighlight: document.getElementById('syntaxHighlightCheckbox').checked, + }; + + // 发送消息到扩展 + vscode.postMessage({ + command: 'saveGeneralSettings', + settings: settings + }); + + // 显示保存成功提示 + console.log('通用设置已保存', settings); + } + + // 重置通用设置 + function resetGeneralSettings() { + document.getElementById('themeSelect').value = 'auto'; + document.getElementById('languageSelect').value = 'zh-CN'; + document.getElementById('autoSaveCheckbox').checked = true; + document.getElementById('showTimestampCheckbox').checked = false; + document.getElementById('fontSizeInput').value = '14'; + document.getElementById('syntaxHighlightCheckbox').checked = true; + + console.log('通用设置已重置为默认值'); + } + + // 加载通用设置 + function loadGeneralSettings(settings) { + if (!settings) return; + + if (settings.theme) { + document.getElementById('themeSelect').value = settings.theme; + } + if (settings.language) { + document.getElementById('languageSelect').value = settings.language; + } + if (settings.autoSave !== undefined) { + document.getElementById('autoSaveCheckbox').checked = settings.autoSave; + } + if (settings.showTimestamp !== undefined) { + document.getElementById('showTimestampCheckbox').checked = settings.showTimestamp; + } + if (settings.fontSize) { + document.getElementById('fontSizeInput').value = settings.fontSize; + } + if (settings.syntaxHighlight !== undefined) { + document.getElementById('syntaxHighlightCheckbox').checked = settings.syntaxHighlight; + } + } + `; +} diff --git a/src/views/rulesSettingsComponent.ts b/src/views/rulesSettingsComponent.ts new file mode 100644 index 0000000..105cfa5 --- /dev/null +++ b/src/views/rulesSettingsComponent.ts @@ -0,0 +1,177 @@ +/** + * 获取规则设置组件的 HTML 内容 + */ +export function getRulesSettingsComponentContent(): string { + return ` +
+

规则设置

+ +
+
+
+ + 使用自定义规则来控制 AI 行为 +
+ +
+
+ +
+

系统规则

+
+ +
+ 系统规则会在每次对话开始时应用 +
+
+
+ +
+

代码生成规则

+
+ +
+ 这些规则会在生成代码时应用 +
+
+
+ +
+

Verilog 规则

+
+ +
+ 这些规则会在生成 Verilog 代码时应用 +
+
+
+ +
+ + +
+
+ `; +} + +/** + * 获取规则设置组件的 CSS 样式 + */ +export function getRulesSettingsComponentStyles(): string { + return ` + .rules-settings { + max-width: 700px; + } + + .rules-textarea-container { + margin-top: 8px; + } + + .rules-textarea { + width: 100%; + padding: 12px; + background: var(--vscode-input-background); + color: var(--vscode-input-foreground); + border: 1px solid var(--vscode-input-border); + border-radius: 4px; + font-size: 13px; + font-family: var(--vscode-editor-font-family); + line-height: 1.5; + resize: vertical; + outline: none; + box-sizing: border-box; + } + + .rules-textarea:focus { + border-color: var(--vscode-focusBorder); + } + + .rules-textarea::placeholder { + color: var(--vscode-input-placeholderForeground); + opacity: 0.6; + } + + .rules-textarea-hint { + margin-top: 8px; + font-size: 12px; + color: var(--vscode-descriptionForeground); + font-style: italic; + } + `; +} + +/** + * 获取规则设置组件的 JavaScript 脚本 + */ +export function getRulesSettingsComponentScript(): string { + return ` + // 保存规则设置 + function saveRulesSettings() { + const settings = { + enableCustomRules: document.getElementById('enableCustomRulesCheckbox').checked, + systemRules: document.getElementById('systemRulesTextarea').value, + codeRules: document.getElementById('codeRulesTextarea').value, + verilogRules: document.getElementById('verilogRulesTextarea').value, + }; + + // 发送消息到扩展 + vscode.postMessage({ + command: 'saveRulesSettings', + settings: settings + }); + + // 显示保存成功提示 + console.log('规则设置已保存', settings); + } + + // 重置规则设置 + function resetRulesSettings() { + document.getElementById('enableCustomRulesCheckbox').checked = true; + document.getElementById('systemRulesTextarea').value = ''; + document.getElementById('codeRulesTextarea').value = ''; + document.getElementById('verilogRulesTextarea').value = ''; + + console.log('规则设置已重置为默认值'); + } + + // 加载规则设置 + function loadRulesSettings(settings) { + if (!settings) return; + + if (settings.enableCustomRules !== undefined) { + document.getElementById('enableCustomRulesCheckbox').checked = settings.enableCustomRules; + } + if (settings.systemRules) { + document.getElementById('systemRulesTextarea').value = settings.systemRules; + } + if (settings.codeRules) { + document.getElementById('codeRulesTextarea').value = settings.codeRules; + } + if (settings.verilogRules) { + document.getElementById('verilogRulesTextarea').value = settings.verilogRules; + } + } + `; +} diff --git a/src/views/settingsComponent.ts b/src/views/settingsComponent.ts new file mode 100644 index 0000000..db24906 --- /dev/null +++ b/src/views/settingsComponent.ts @@ -0,0 +1,248 @@ +import { + getGeneralSettingsComponentContent, + getGeneralSettingsComponentStyles, + getGeneralSettingsComponentScript, +} from "./generalSettingsComponent"; +import { + getRulesSettingsComponentContent, + getRulesSettingsComponentStyles, + getRulesSettingsComponentScript, +} from "./rulesSettingsComponent"; + +/** + * 获取设置面板的 HTML 内容 + */ +export function getSettingsComponentContent(): string { + return ` +
+
+
+
+

设置

+ +
+ +
+
+ + +
+ +
+
+ ${getGeneralSettingsComponentContent()} +
+
+ ${getRulesSettingsComponentContent()} +
+
+
+
+
+ `; +} + +/** + * 获取设置面板的 CSS 样式 + */ +export function getSettingsComponentStyles(): string { + return ` + .settings-modal { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 9999; + } + + .settings-modal.active { + display: flex; + align-items: center; + justify-content: center; + } + + .settings-modal-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + } + + .settings-modal-content { + position: relative; + width: 90%; + max-width: 800px; + height: 80%; + max-height: 600px; + background: var(--vscode-editor-background); + border: 1px solid var(--vscode-panel-border); + border-radius: 8px; + display: flex; + flex-direction: column; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); + } + + .settings-modal-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 20px; + border-bottom: 1px solid var(--vscode-panel-border); + flex-shrink: 0; + } + + .settings-modal-title { + margin: 0; + font-size: 18px; + font-weight: 600; + color: var(--vscode-foreground); + } + + .settings-modal-close { + width: 32px; + height: 32px; + padding: 0; + background: transparent; + border: none; + border-radius: 4px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: var(--vscode-foreground); + transition: all 0.2s ease; + } + + .settings-modal-close:hover { + background: var(--vscode-toolbar-hoverBackground); + } + + .settings-modal-close svg { + width: 20px; + height: 20px; + } + + .settings-modal-body { + display: flex; + flex: 1; + overflow: hidden; + } + + .settings-nav { + width: 180px; + padding: 16px 0; + border-right: 1px solid var(--vscode-panel-border); + flex-shrink: 0; + overflow-y: auto; + } + + .settings-nav-item { + width: 100%; + padding: 10px 20px; + background: transparent; + border: none; + text-align: left; + font-size: 14px; + color: var(--vscode-foreground); + cursor: pointer; + transition: all 0.2s ease; + border-left: 3px solid transparent; + } + + .settings-nav-item:hover { + background: var(--vscode-list-hoverBackground); + } + + .settings-nav-item.active { + background: var(--vscode-list-activeSelectionBackground); + color: var(--vscode-list-activeSelectionForeground); + border-left-color: var(--vscode-focusBorder); + } + + .settings-content { + flex: 1; + overflow-y: auto; + padding: 20px; + } + + .settings-tab-content { + display: none; + } + + .settings-tab-content.active { + display: block; + } + + ${getGeneralSettingsComponentStyles()} + ${getRulesSettingsComponentStyles()} + `; +} + +/** + * 获取设置面板的 JavaScript 脚本 + */ +export function getSettingsComponentScript(): string { + return ` + ${getGeneralSettingsComponentScript()} + ${getRulesSettingsComponentScript()} + + // 打开设置面板 + function openSettingsModal() { + const modal = document.getElementById('settingsModal'); + if (modal) { + modal.classList.add('active'); + } + } + + // 关闭设置面板 + function closeSettingsModal() { + const modal = document.getElementById('settingsModal'); + if (modal) { + modal.classList.remove('active'); + } + } + + // 切换设置标签页 + function switchSettingsTab(tabName) { + // 更新导航项状态 + const navItems = document.querySelectorAll('.settings-nav-item'); + navItems.forEach(item => { + if (item.dataset.tab === tabName) { + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + + // 更新内容区域 + const tabContents = document.querySelectorAll('.settings-tab-content'); + tabContents.forEach(content => { + if (content.id === tabName + 'Settings') { + content.classList.add('active'); + } else { + content.classList.remove('active'); + } + }); + } + + // 阻止点击模态框内容时关闭 + document.addEventListener('click', (event) => { + const modalContent = document.querySelector('.settings-modal-content'); + if (modalContent && modalContent.contains(event.target)) { + event.stopPropagation(); + } + }); + `; +}