feat: 实现状态栏显示功能
- 在消息区域下方添加状态栏 UI(HTML、CSS、JS) - 支持"思考中..."状态显示(蓝色脉冲动画) - 支持"生成中..."状态显示(橙色脉冲动画) - 支持工具执行时显示"正在执行 xxx..." - 在 messageHandler 中添加状态栏消息发送逻辑
This commit is contained in:
@ -105,18 +105,29 @@ async function handleUserMessageWithBackend(
|
|||||||
|
|
||||||
const historyManager = ChatHistoryManager.getInstance();
|
const historyManager = ChatHistoryManager.getInstance();
|
||||||
|
|
||||||
// 显示加载状态
|
// 显示状态栏
|
||||||
panel.webview.postMessage({
|
panel.webview.postMessage({
|
||||||
command: "showLoading",
|
command: "updateStatus",
|
||||||
text: "正在思考...",
|
text: "思考中...",
|
||||||
|
type: "thinking",
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
currentSession!.sendMessage(text, {
|
currentSession!.sendMessage(text, {
|
||||||
onText: (fullText, isStreaming) => {
|
onText: (fullText, isStreaming) => {
|
||||||
// 暂时只在完成时发送消息(非流式)
|
if (isStreaming) {
|
||||||
if (!isStreaming) {
|
// 流式时更新状态为"生成中"
|
||||||
|
panel.webview.postMessage({
|
||||||
|
command: "updateStatus",
|
||||||
|
text: "生成中...",
|
||||||
|
type: "working",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 完成时发送消息并隐藏状态
|
||||||
console.log('[MessageHandler] 发送最终消息, 文本长度:', fullText.length);
|
console.log('[MessageHandler] 发送最终消息, 文本长度:', fullText.length);
|
||||||
|
panel.webview.postMessage({
|
||||||
|
command: "hideStatus",
|
||||||
|
});
|
||||||
panel.webview.postMessage({
|
panel.webview.postMessage({
|
||||||
command: "receiveMessage",
|
command: "receiveMessage",
|
||||||
text: fullText,
|
text: fullText,
|
||||||
|
|||||||
@ -680,6 +680,41 @@ export function getWebviewContent(iconUri?: string): string {
|
|||||||
.question-message.answered .custom-input-container {
|
.question-message.answered .custom-input-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 状态栏样式 */
|
||||||
|
.status-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
background: var(--vscode-textBlockQuote-background);
|
||||||
|
border-radius: 6px;
|
||||||
|
margin: 8px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--vscode-descriptionForeground);
|
||||||
|
}
|
||||||
|
.status-indicator {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--vscode-charts-blue);
|
||||||
|
animation: statusPulse 1.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes statusPulse {
|
||||||
|
0%, 100% { opacity: 1; transform: scale(1); }
|
||||||
|
50% { opacity: 0.5; transform: scale(0.8); }
|
||||||
|
}
|
||||||
|
.status-bar.working .status-indicator {
|
||||||
|
background: var(--vscode-charts-orange);
|
||||||
|
}
|
||||||
|
.status-bar.success .status-indicator {
|
||||||
|
background: var(--vscode-charts-green);
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
.status-bar.error .status-indicator {
|
||||||
|
background: var(--vscode-charts-red);
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -722,6 +757,12 @@ export function getWebviewContent(iconUri?: string): string {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 状态栏 -->
|
||||||
|
<div id="statusBar" class="status-bar" style="display: none;">
|
||||||
|
<div class="status-indicator"></div>
|
||||||
|
<span id="statusText">思考中...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="quick-actions">
|
<div class="quick-actions">
|
||||||
<button class="quick-btn" onclick="quickAction('counter')">生成计数器</button>
|
<button class="quick-btn" onclick="quickAction('counter')">生成计数器</button>
|
||||||
<button class="quick-btn" onclick="quickAction('fsm')">生成状态机</button>
|
<button class="quick-btn" onclick="quickAction('fsm')">生成状态机</button>
|
||||||
@ -1116,11 +1157,19 @@ export function getWebviewContent(iconUri?: string): string {
|
|||||||
case 'hideLoading':
|
case 'hideLoading':
|
||||||
hideLoadingIndicator();
|
hideLoadingIndicator();
|
||||||
break;
|
break;
|
||||||
|
case 'updateStatus':
|
||||||
|
updateStatusBar(message.text, message.type || 'thinking');
|
||||||
|
break;
|
||||||
|
case 'hideStatus':
|
||||||
|
hideStatusBar();
|
||||||
|
break;
|
||||||
case 'toolStart':
|
case 'toolStart':
|
||||||
addToolStatus(message.toolName, 'start');
|
addToolStatus(message.toolName, 'start');
|
||||||
|
updateStatusBar('正在执行 ' + message.toolName + '...', 'working');
|
||||||
break;
|
break;
|
||||||
case 'toolComplete':
|
case 'toolComplete':
|
||||||
addToolStatus(message.toolName, 'complete', message.result);
|
addToolStatus(message.toolName, 'complete', message.result);
|
||||||
|
hideStatusBar();
|
||||||
break;
|
break;
|
||||||
case 'toolError':
|
case 'toolError':
|
||||||
addToolStatus(message.toolName, 'error', message.error);
|
addToolStatus(message.toolName, 'error', message.error);
|
||||||
@ -1224,6 +1273,25 @@ export function getWebviewContent(iconUri?: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新状态栏
|
||||||
|
function updateStatusBar(text, type) {
|
||||||
|
const statusBar = document.getElementById('statusBar');
|
||||||
|
const statusText = document.getElementById('statusText');
|
||||||
|
if (statusBar && statusText) {
|
||||||
|
statusText.textContent = text;
|
||||||
|
statusBar.className = 'status-bar ' + (type || 'thinking');
|
||||||
|
statusBar.style.display = 'flex';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏状态栏
|
||||||
|
function hideStatusBar() {
|
||||||
|
const statusBar = document.getElementById('statusBar');
|
||||||
|
if (statusBar) {
|
||||||
|
statusBar.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 添加工具状态消息
|
// 添加工具状态消息
|
||||||
function addToolStatus(toolName, status, detail) {
|
function addToolStatus(toolName, status, detail) {
|
||||||
const statusIcons = {
|
const statusIcons = {
|
||||||
|
|||||||
Reference in New Issue
Block a user