@@ -65,6 +65,7 @@ export class ChatPanel {
6565 private readonly _panel : vscode . WebviewPanel ;
6666 private _disposables : vscode . Disposable [ ] = [ ] ;
6767 private _conversation : { role : string , content : string } [ ] = [ ] ;
68+ private _userMessageIndex : number = 0 ;
6869
6970 private constructor ( panel : vscode . WebviewPanel ) {
7071 this . _panel = panel ;
@@ -114,13 +115,29 @@ export class ChatPanel {
114115 padding: 8px;
115116 }
116117 .user {
118+ position: relative;
117119 background-color: #a3a3a3;
118120 color: black;
119- padding: 12px;
121+ padding: 12px 12px 12px 40px ;
120122 margin: 8px 0;
121123 border-radius: 4px;
122124 white-space: pre-wrap;
123125 }
126+ .edit-btn {
127+ position: absolute;
128+ left: 8px;
129+ top: 50%;
130+ transform: translateY(-50%);
131+ display: none;
132+ background: none;
133+ border: none;
134+ color: #fff;
135+ cursor: pointer;
136+ padding: 4px;
137+ }
138+ .user:hover .edit-btn {
139+ display: block;
140+ }
124141 .model {
125142 background-color: #333;
126143 color: white;
@@ -213,6 +230,46 @@ export class ChatPanel {
213230 const sendButton = document.getElementById('send');
214231 const stopButton = document.getElementById('stop');
215232
233+ function addEditButtons() {
234+ document.querySelectorAll('.edit-btn').forEach(btn => {
235+ btn.onclick = function(event) {
236+ const userDiv = event.target.closest('.user');
237+ const contentDiv = userDiv.querySelector('.user-content');
238+ userDiv.innerHTML = \`
239+ <textarea class="edit-textarea">\${contentDiv.textContent}</textarea>
240+ <div class="edit-buttons">
241+ <button class="edit-send">发送</button>
242+ <button class="edit-cancel">取消</button>
243+ </div>
244+ \`;
245+
246+ userDiv.querySelector('.edit-send').onclick = () => {
247+ const newText = userDiv.querySelector('textarea').value;
248+ vscode.postMessage({
249+ command: 'editMessage',
250+ index: parseInt(userDiv.dataset.index),
251+ text: newText
252+ });
253+ // 立即更新当前消息显示
254+ userDiv.innerHTML = \`
255+ <button class="edit-btn">✎</button>
256+ <div class="user-content">\${newText}</div>
257+ \`;
258+ addEditButtons();
259+ userDiv.querySelectorAll('.model').forEach(m => m.remove());
260+ };
261+
262+ userDiv.querySelector('.edit-cancel').onclick = () => {
263+ userDiv.innerHTML = \`
264+ <button class="edit-btn">✎</button>
265+ <div class="user-content">\${contentDiv.textContent}</div>
266+ \`;
267+ addEditButtons();
268+ };
269+ };
270+ });
271+ }
272+
216273 function addCopyButtons() {
217274 document.querySelectorAll('pre').forEach(pre => {
218275 if (pre.querySelector('.copy-btn')) return;
@@ -289,9 +346,14 @@ export class ChatPanel {
289346 // 重新高亮代码块
290347 hljs.highlightAll();
291348 } else {
292- // 用户消息保持纯文本
293- targetDiv.textContent = targetDiv.dataset.markdownContent;
349+ // 用户消息保持纯文本并添加编辑功能
350+ targetDiv.innerHTML = \`
351+ <button class="edit-btn">✎</button>
352+ <div class="user-content">\${targetDiv.dataset.markdownContent}</div>
353+ \`;
354+ targetDiv.dataset.index = data.index;
294355 }
356+ addEditButtons();
295357
296358 chat.scrollTop = chat.scrollHeight;
297359 }
@@ -313,6 +375,19 @@ export class ChatPanel {
313375 case 'hideStopButton':
314376 stopButton.style.display = 'none';
315377 break;
378+ case 'clearAfterIndex':
379+ const clearIndex = data.index;
380+ document.querySelectorAll('.user').forEach(userDiv => {
381+ const userIndex = parseInt(userDiv.dataset.index);
382+ if (userIndex >= clearIndex) {
383+ const modelDiv = userDiv.nextElementSibling;
384+ if (modelDiv && modelDiv.classList.contains('model')) {
385+ modelDiv.remove();
386+ }
387+ userDiv.remove();
388+ }
389+ });
390+ break;
316391 default:
317392 // 处理其他 command 消息
318393 break;
@@ -322,7 +397,10 @@ export class ChatPanel {
322397
323398 // 发送消息逻辑
324399 document.getElementById('send').addEventListener('click', () => {
325- vscode.postMessage({ command: 'sendMessage', text: input.value });
400+ vscode.postMessage({
401+ command: 'sendMessage',
402+ text: input.value
403+ });
326404 input.value = '';
327405 });
328406
@@ -339,7 +417,10 @@ export class ChatPanel {
339417
340418 input.addEventListener('keydown', (e) => {
341419 if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
342- vscode.postMessage({ command: 'sendMessage', text: input.value });
420+ vscode.postMessage({
421+ command: 'sendMessage',
422+ text: input.value
423+ });
343424 input.value = '';
344425 }
345426 });
@@ -353,9 +434,17 @@ export class ChatPanel {
353434 const webviewOutputChannel = new WebviewOutputChannel ( this . _panel . webview , 'DeepSeek API Output' ) ;
354435
355436 switch ( message . command ) {
437+ case 'editMessage' :
438+ if ( message . index < this . _conversation . length ) {
439+ this . _conversation . splice ( message . index + 1 ) ;
440+ this . _panel . webview . postMessage ( { command : 'clearAfterIndex' , index : message . index } ) ;
441+ this . _userMessageIndex = message . index ;
442+ }
443+ // break; 复用下面的send
356444 case 'sendMessage' :
357445 this . _conversation . push ( { role : 'user' , content : message . text } ) ;
358- this . _panel . webview . postMessage ( { role : 'user' , content : message . text } ) ;
446+ this . _panel . webview . postMessage ( { role : 'user' , content : message . text , index : this . _userMessageIndex } ) ;
447+ this . _userMessageIndex ++ ;
359448
360449 try {
361450 // 发送消息到 Webview,禁用发送按钮并显示停止按钮
@@ -390,7 +479,9 @@ export class ChatPanel {
390479
391480 case 'newSession' :
392481 this . _conversation = [ ] ;
482+ this . _userMessageIndex = 0 ;
393483 resetCurrentOperationController ( ) ;
484+ this . _panel . webview . postMessage ( { command : 'clearAfterIndex' , index : - 1 } ) ;
394485 break ;
395486 case 'stop' :
396487 resetCurrentOperationController ( ) ;
0 commit comments