diff --git a/static/app.js b/static/app.js index 64fc900..e5cfd51 100644 --- a/static/app.js +++ b/static/app.js @@ -200,8 +200,10 @@ async function bootstrapApp() { // 对话压缩状态 compressing: false, - // 设置菜单状态 + // 输入/快捷菜单状态 settingsOpen: false, + quickMenuOpen: false, + inputLineCount: 1, // 思考块滚动锁 thinkingScrollLocks: new Map(), @@ -254,8 +256,7 @@ async function bootstrapApp() { this.loadInitialData(); }, 500); - document.addEventListener('click', this.handleClickOutsideSettings); - document.addEventListener('click', this.handleClickOutsideToolMenu); + document.addEventListener('click', this.handleClickOutsideQuickMenu); document.addEventListener('click', this.handleClickOutsidePanelMenu); window.addEventListener('popstate', this.handlePopState); @@ -291,11 +292,14 @@ async function bootstrapApp() { this.fetchSubAgents(); } }, 5000); + + this.$nextTick(() => { + this.autoResizeInput(); + }); }, beforeUnmount() { - document.removeEventListener('click', this.handleClickOutsideSettings); - document.removeEventListener('click', this.handleClickOutsideToolMenu); + document.removeEventListener('click', this.handleClickOutsideQuickMenu); document.removeEventListener('click', this.handleClickOutsidePanelMenu); window.removeEventListener('popstate', this.handlePopState); if (this.onDocumentClick) { @@ -315,6 +319,12 @@ async function bootstrapApp() { this.subAgentPollTimer = null; } }, + + watch: { + inputMessage() { + this.autoResizeInput(); + } + }, methods: { openGuiFileManager() { @@ -1310,6 +1320,8 @@ async function bootstrapApp() { this.settingsOpen = false; this.toolMenuOpen = false; + this.quickMenuOpen = false; + this.inputLineCount = 1; this.toolSettingsLoading = false; this.toolSettings = []; @@ -1696,6 +1708,9 @@ async function bootstrapApp() { const metadata = message.metadata || {}; const appendPayloadMeta = metadata.append_payload; const modifyPayloadMeta = metadata.modify_payload; + const isAppendMessage = message.name === 'append_to_file'; + const isModifyMessage = message.name === 'modify_file'; + const containsAppendMarkers = /<<<\s*(APPEND|MODIFY)/i.test(content || '') || /<<>>/i.test(content || ''); let textContent = content; if (!message.reasoning_content) { @@ -1738,7 +1753,7 @@ async function bootstrapApp() { console.log('添加modify占位信息:', modifyPayloadMeta.path); } - if (textContent && !appendPayloadMeta && !modifyPayloadMeta) { + if (textContent && !appendPayloadMeta && !modifyPayloadMeta && !isAppendMessage && !isModifyMessage && !containsAppendMarkers) { currentAssistantMessage.actions.push({ id: `history-text-${Date.now()}-${Math.random()}`, type: 'text', @@ -1822,22 +1837,7 @@ async function bootstrapApp() { } console.log(`更新工具结果: ${message.name} -> ${message.content?.substring(0, 50)}...`); - if (message.name === 'append_to_file' && result && typeof result === 'object') { - const appendSummary = { - path: result.path || '未知文件', - success: result.success !== false, - summary: result.message || (result.success === false ? '追加失败' : '追加完成'), - lines: result.lines || 0, - bytes: result.bytes || 0, - forced: !!result.forced - }; - currentAssistantMessage.actions.push({ - id: `history-append-${Date.now()}-${Math.random()}`, - type: 'append', - append: appendSummary, - timestamp: Date.now() - }); - } + // append_to_file 的摘要在 append_payload 占位中呈现,此处无需重复 } else { console.warn('找不到对应的工具调用:', message.name, message.tool_call_id); } @@ -2319,7 +2319,7 @@ async function bootstrapApp() { if (message.startsWith('/')) { this.socket.emit('send_command', { command: message }); this.inputMessage = ''; - this.settingsOpen = false; + this.autoResizeInput(); return; } @@ -2333,7 +2333,7 @@ async function bootstrapApp() { this.inputMessage = ''; this.autoScrollEnabled = true; this.scrollToBottom(); - this.settingsOpen = false; + this.autoResizeInput(); // 发送消息后延迟更新当前上下文Token(关键修复:恢复原逻辑) setTimeout(() => { @@ -2350,14 +2350,12 @@ async function bootstrapApp() { this.stopRequested = true; console.log('发送停止请求'); } - this.settingsOpen = false; }, clearChat() { if (confirm('确定要清除所有对话记录吗?')) { this.socket.emit('send_command', { command: '/clear' }); } - this.settingsOpen = false; }, async compressConversation() { @@ -2375,7 +2373,6 @@ async function bootstrapApp() { return; } - this.settingsOpen = false; this.compressing = true; try { @@ -2411,19 +2408,75 @@ async function bootstrapApp() { this.toolMenuOpen = nextState; if (nextState) { this.settingsOpen = false; + if (!this.quickMenuOpen) { + this.quickMenuOpen = true; + } this.loadToolSettings(); } }, - handleClickOutsideToolMenu(event) { - if (!this.toolMenuOpen) { + toggleQuickMenu() { + if (!this.isConnected) { return; } - const dropdown = this.$refs.toolDropdown; - if (dropdown && !dropdown.contains(event.target)) { + const nextState = !this.quickMenuOpen; + this.quickMenuOpen = nextState; + if (!nextState) { this.toolMenuOpen = false; + this.settingsOpen = false; } }, + + closeQuickMenu() { + this.quickMenuOpen = false; + this.toolMenuOpen = false; + this.settingsOpen = false; + }, + + handleQuickUpload() { + if (this.uploading || !this.isConnected) { + return; + } + this.triggerFileUpload(); + }, + + handleQuickModeToggle() { + if (!this.isConnected || this.streamingMessage) { + return; + } + this.toggleThinkingMode(); + }, + + handleInputChange() { + this.autoResizeInput(); + }, + + autoResizeInput() { + this.$nextTick(() => { + const textarea = this.$refs.stadiumInput; + if (!textarea) { + return; + } + textarea.style.height = 'auto'; + const computedStyle = window.getComputedStyle(textarea); + const lineHeight = parseFloat(computedStyle.lineHeight || '20') || 20; + const maxHeight = lineHeight * 6; + const newHeight = Math.min(textarea.scrollHeight, maxHeight); + textarea.style.height = `${newHeight}px`; + this.inputLineCount = Math.max(1, Math.round(newHeight / lineHeight)); + }); + }, + + handleClickOutsideQuickMenu(event) { + if (!this.quickMenuOpen) { + return; + } + const shell = this.$refs.compactInputShell; + if (shell && shell.contains(event.target)) { + return; + } + this.closeQuickMenu(); + }, handleClickOutsidePanelMenu(event) { if (!this.panelMenuOpen) { @@ -2518,9 +2571,13 @@ async function bootstrapApp() { if (!this.isConnected) { return; } - this.settingsOpen = !this.settingsOpen; - if (this.settingsOpen) { + const nextState = !this.settingsOpen; + this.settingsOpen = nextState; + if (nextState) { this.toolMenuOpen = false; + if (!this.quickMenuOpen) { + this.quickMenuOpen = true; + } } }, @@ -2529,19 +2586,8 @@ async function bootstrapApp() { if (!this.rightCollapsed && this.rightWidth < this.minPanelWidth) { this.rightWidth = this.minPanelWidth; } - this.settingsOpen = false; }, - handleClickOutsideSettings(event) { - if (!this.settingsOpen) { - return; - } - const dropdown = this.$refs.settingsDropdown; - if (dropdown && !dropdown.contains(event.target)) { - this.settingsOpen = false; - } - }, - addSystemMessage(content) { this.appendSystemAction(content); }, diff --git a/static/index.html b/static/index.html index ade0bf9..bf33efa 100644 --- a/static/index.html +++ b/static/index.html @@ -38,21 +38,6 @@