11import * as vscode from 'vscode' ;
22import { callDeepSeekApi } from './deepseekApi' ;
33
4+ class WebviewOutputChannel implements vscode . OutputChannel {
5+ private _webview : vscode . Webview ;
6+ private _name : string ;
7+
8+ constructor ( webview : vscode . Webview , name : string ) {
9+ this . _webview = webview ;
10+ this . _name = name ;
11+ }
12+
13+ get name ( ) : string {
14+ return this . _name ;
15+ }
16+
17+ append ( value : string ) : void {
18+ // 将数据通过 Webview 发送出去
19+ this . _webview . postMessage ( { role : 'model' , content : value } ) ;
20+ }
21+
22+ appendLine ( value : string ) : void {
23+ this . append ( value + '\n' ) ;
24+ }
25+
26+ clear ( ) : void {
27+ // 清除输出,通常可以通过清空 Webview 来实现
28+ this . _webview . postMessage ( { role : 'model' , content : '' } ) ;
29+ }
30+
31+ show ( preserveFocus ?: boolean ) : void ;
32+ show ( column ?: vscode . ViewColumn , preserveFocus ?: boolean ) : void ;
33+ show ( arg1 ?: boolean | vscode . ViewColumn , arg2 ?: boolean ) : void {
34+ if ( typeof arg1 === 'boolean' ) {
35+ // 第一种重载:show(preserveFocus?: boolean)
36+ this . _webview . postMessage ( { role : 'model' , content : 'Webview is now shown' } ) ;
37+ } else {
38+ // 第二种重载:show(column?: ViewColumn, preserveFocus?: boolean)
39+ if ( arg1 !== undefined ) {
40+ // 根据 column 进行处理(可以自定义逻辑)
41+ console . log ( `Showing in column: ${ arg1 } ` ) ;
42+ }
43+ this . _webview . postMessage ( { role : 'model' , content : 'Webview is now shown' } ) ;
44+ }
45+ }
46+ hide ( ) : void {
47+
48+ }
49+
50+ dispose ( ) : void {
51+
52+ }
53+
54+ replace ( value : string ) : void {
55+ // 替换输出内容
56+ this . _webview . postMessage ( { role : 'model' , content : value } ) ;
57+ }
58+ }
59+
60+
461export class ChatPanel {
562 private static readonly viewType = 'chatPanel' ;
663 private static currentPanel : ChatPanel | undefined ;
@@ -60,6 +117,10 @@ export class ChatPanel {
60117 background-color: white;
61118 padding: 10px;
62119 }
120+ #chat div {
121+ white-space: pre-wrap; /* 关键代码:保留换行符 */
122+ margin-bottom: 8px; /* 段落间距(可选) */
123+ }
63124 </style>
64125 </head>
65126 <body>
@@ -102,10 +163,21 @@ export class ChatPanel {
102163
103164 window.addEventListener('message', (event) => {
104165 const { role, content } = event.data;
105- const div = document.createElement('div');
106- div.className = role;
107- div.textContent = content;
108- chat.appendChild(div);
166+ const chat = document.getElementById('chat');
167+ const lastChild = chat.lastElementChild;
168+
169+ // 合并到同一角色元素
170+ if (lastChild && lastChild.className === role) {
171+ lastChild.textContent += content;
172+ } else {
173+ const div = document.createElement('div');
174+ div.className = role;
175+ div.textContent = content;
176+ chat.appendChild(div);
177+ }
178+
179+ // 自动滚动到底部
180+ chat.scrollTop = chat.scrollHeight;
109181 });
110182 </script>
111183 </body>
@@ -114,11 +186,13 @@ export class ChatPanel {
114186 }
115187
116188 private async _handleMessage ( message : any ) {
189+ const webviewOutputChannel = new WebviewOutputChannel ( this . _panel . webview , 'DeepSeek API Output' ) ;
190+
117191 switch ( message . command ) {
118192 case 'sendMessage' :
119193 this . _conversation . push ( { role : 'user' , content : message . text } ) ;
120194 this . _panel . webview . postMessage ( { role : 'user' , content : message . text } ) ;
121- const response = await callDeepSeekApi ( message . text , 'You are a helpful assistant.' ) ;
195+ const response = await callDeepSeekApi ( message . text , 'You are a helpful assistant.' , webviewOutputChannel , true ) ;
122196 this . _conversation . push ( { role : 'model' , content : response || '' } ) ;
123197 this . _panel . webview . postMessage ( { role : 'model' , content : response || '' } ) ;
124198 break ;
0 commit comments