2 Commits

Author SHA1 Message Date
e61122449d feat:暂存修改+还未测试 2026-01-10 10:19:49 +08:00
4687c3faa6 feat:设置最小宽度
- 小于最小宽度就自动关闭面板并且提供提示
2026-01-10 09:18:00 +08:00
4 changed files with 195 additions and 44 deletions

View File

@ -33,10 +33,10 @@ function getTierIconUri(
} }
const tierIconMap: Record<string, string> = { const tierIconMap: Record<string, string> = {
'BASIC': 'free.png', BASIC: "free.png",
'TRIAL': 'PRO-Try.png', TRIAL: "PRO-Try.png",
'ADVANCED': 'PRO.png', ADVANCED: "PRO.png",
'PROFESSIONAL': 'PRO+.png' PROFESSIONAL: "PRO+.png",
}; };
const iconFile = tierIconMap[tierCode]; const iconFile = tierIconMap[tierCode];
@ -45,7 +45,13 @@ function getTierIconUri(
} }
const iconUri = webview.asWebviewUri( const iconUri = webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, 'src', 'assets', 'titleIcon', iconFile) vscode.Uri.joinPath(
context.extensionUri,
"src",
"assets",
"titleIcon",
iconFile
)
); );
return iconUri.toString(); return iconUri.toString();
@ -94,7 +100,7 @@ export async function showICHelperPanel(
retainContextWhenHidden: true, retainContextWhenHidden: true,
localResourceRoots: [ localResourceRoots: [
vscode.Uri.joinPath(context.extensionUri, "media"), vscode.Uri.joinPath(context.extensionUri, "media"),
vscode.Uri.joinPath(context.extensionUri, "src", "assets") vscode.Uri.joinPath(context.extensionUri, "src", "assets"),
], ],
} }
); );
@ -119,16 +125,40 @@ export async function showICHelperPanel(
// 获取模型图标URI // 获取模型图标URI
const autoIconUri = panel.webview.asWebviewUri( const autoIconUri = panel.webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Auto.png") vscode.Uri.joinPath(
context.extensionUri,
"src",
"assets",
"model",
"Auto.png"
)
); );
const liteIconUri = panel.webview.asWebviewUri( const liteIconUri = panel.webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "lite.png") vscode.Uri.joinPath(
context.extensionUri,
"src",
"assets",
"model",
"lite.png"
)
); );
const syIconUri = panel.webview.asWebviewUri( const syIconUri = panel.webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Sy.png") vscode.Uri.joinPath(
context.extensionUri,
"src",
"assets",
"model",
"Sy.png"
)
); );
const maxIconUri = panel.webview.asWebviewUri( const maxIconUri = panel.webview.asWebviewUri(
vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Max.png") vscode.Uri.joinPath(
context.extensionUri,
"src",
"assets",
"model",
"Max.png"
)
); );
// 设置HTML内容 // 设置HTML内容
@ -147,16 +177,20 @@ export async function showICHelperPanel(
if (userInfo) { if (userInfo) {
// 使用缓存的用户信息 // 使用缓存的用户信息
console.log('[ICHelperPanel] 使用缓存的用户信息:', userInfo); console.log("[ICHelperPanel] 使用缓存的用户信息:", userInfo);
const tierIconUrl = getTierIconUri(panel.webview, context, userInfo.membership?.tierCode); const tierIconUrl = getTierIconUri(
panel.webview,
context,
userInfo.membership?.tierCode
);
panel.webview.postMessage({ panel.webview.postMessage({
command: 'updateUserInfo', command: "updateUserInfo",
userInfo: { userInfo: {
userId: userInfo.userId, userId: userInfo.userId,
nickname: userInfo.nickname, nickname: userInfo.nickname,
username: userInfo.username username: userInfo.username,
}, },
tierIconUrl: tierIconUrl tierIconUrl: tierIconUrl,
}); });
} else { } else {
// 如果没有缓存,从 session 中获取 // 如果没有缓存,从 session 中获取
@ -164,19 +198,22 @@ export async function showICHelperPanel(
createIfNone: false, createIfNone: false,
}); });
if (session) { if (session) {
console.log('[ICHelperPanel] 从 session 获取用户信息, account:', session.account); console.log(
"[ICHelperPanel] 从 session 获取用户信息, account:",
session.account
);
panel.webview.postMessage({ panel.webview.postMessage({
command: 'updateUserInfo', command: "updateUserInfo",
userInfo: { userInfo: {
userId: session.account.id, userId: session.account.id,
nickname: session.account.label, nickname: session.account.label,
username: session.account.label username: session.account.label,
} },
}); });
} }
} }
} catch (error) { } catch (error) {
console.error('[ICHelperPanel] 获取用户信息失败:', error); console.error("[ICHelperPanel] 获取用户信息失败:", error);
} }
// 处理消息 // 处理消息
@ -213,14 +250,14 @@ export async function showICHelperPanel(
historyManager.switchToPanelTask(panelId); historyManager.switchToPanelTask(panelId);
// 显示进度条 // 显示进度条
panel.webview.postMessage({ type: 'showProgress' }); panel.webview.postMessage({ type: "showProgress" });
handleUserMessage( handleUserMessage(
panel, panel,
message.text, message.text,
context.extensionPath, context.extensionPath,
message.mode, message.mode,
message.model // 传递服务等级 message.model // 传递服务等级
); );
break; break;
case "readFile": case "readFile":
@ -249,7 +286,10 @@ export async function showICHelperPanel(
case "openWaveformViewer": case "openWaveformViewer":
// 在新列中打开波形查看器 // 在新列中打开波形查看器
if (message.vcdFilePath) { if (message.vcdFilePath) {
vscode.commands.executeCommand('ic-coder.openVCDViewer', message.vcdFilePath); vscode.commands.executeCommand(
"ic-coder.openVCDViewer",
message.vcdFilePath
);
} }
break; break;
case "getVCDInfo": case "getVCDInfo":
@ -392,7 +432,11 @@ export async function showICHelperPanel(
try { try {
const items = fs.readdirSync(dir, { withFileTypes: true }); const items = fs.readdirSync(dir, { withFileTypes: true });
for (const item of items) { for (const item of items) {
if (item.isDirectory() && item.name !== "node_modules" && !item.name.startsWith(".")) { if (
item.isDirectory() &&
item.name !== "node_modules" &&
!item.name.startsWith(".")
) {
const fullPath = path.join(dir, item.name); const fullPath = path.join(dir, item.name);
const relativePath = path.relative(baseDir, fullPath); const relativePath = path.relative(baseDir, fullPath);
folders.push({ path: fullPath, relativePath }); folders.push({ path: fullPath, relativePath });
@ -421,7 +465,7 @@ export async function showICHelperPanel(
canSelectMany: true, canSelectMany: true,
openLabel: "选择图片", openLabel: "选择图片",
filters: { filters: {
"图片文件": ["png", "jpg", "jpeg", "gif", "bmp", "svg", "webp"], : ["png", "jpg", "jpeg", "gif", "bmp", "svg", "webp"],
}, },
}); });
if (imageUris && imageUris.length > 0) { if (imageUris && imageUris.length > 0) {
@ -441,8 +485,8 @@ export async function showICHelperPanel(
canSelectMany: true, canSelectMany: true,
openLabel: "选择文档", openLabel: "选择文档",
filters: { filters: {
"文档文件": ["pdf", "doc", "docx", "txt", "md"], : ["pdf", "doc", "docx", "txt", "md"],
"所有文件": ["*"], : ["*"],
}, },
}); });
if (docUris && docUris.length > 0) { if (docUris && docUris.length > 0) {
@ -478,6 +522,29 @@ export async function showICHelperPanel(
hasWorkspace: hasWorkspace, hasWorkspace: hasWorkspace,
}); });
break; break;
// 新增:处理面板宽度不足
case "panelWidthInsufficient":
// 关闭面板
panel.dispose();
vscode.window.showWarningMessage(
"聊天面板宽度不足(最小 200px已自动关闭"
);
break;
}
},
undefined,
context.subscriptions
);
// 监听面板状态变化,检查宽度
panel.onDidChangeViewState(
(e) => {
if (e.webviewPanel.visible) {
// 请求前端检查宽度
panel.webview.postMessage({
command: "checkPanelWidth",
minWidth: 200,
});
} }
}, },
undefined, undefined,
@ -508,8 +575,12 @@ async function getVCDFileInfo(
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
console.log(`[getVCDFileInfo] 开始解析 VCD 文件: ${vcdFilePath}`);
console.log(`[getVCDFileInfo] containerId: ${containerId}`);
// 检查文件是否存在 // 检查文件是否存在
if (!fs.existsSync(vcdFilePath)) { if (!fs.existsSync(vcdFilePath)) {
console.error(`[getVCDFileInfo] 文件不存在: ${vcdFilePath}`);
panel.webview.postMessage({ panel.webview.postMessage({
command: "vcdInfo", command: "vcdInfo",
containerId: containerId, containerId: containerId,
@ -548,8 +619,14 @@ async function getVCDFileInfo(
timeRange = `${minTime} - ${maxTime}`; timeRange = `${minTime} - ${maxTime}`;
} }
// 解析前几个信号的真实数据 // 解析信号的真实数据
const signals = parseVCDSignals(content, 3); // 只解析前3个信号 // 增加到20个信号以便显示更多波形平衡性能和完整性
const signals = parseVCDSignals(content, 20);
console.log(`[getVCDFileInfo] 解析到 ${signals.length} 个有效信号`);
signals.forEach((sig, idx) => {
console.log(`[getVCDFileInfo] 信号${idx + 1}: ${sig.name}, 值变化数: ${sig.values.length}`);
});
// 发送信息回前端 // 发送信息回前端
panel.webview.postMessage({ panel.webview.postMessage({
@ -637,10 +714,13 @@ function parseVCDSignals(content: string, maxSignals: number = 3) {
// 解析信号值变化 // 解析信号值变化
// 格式1: 单比特信号 "0!" 或 "1!" // 格式1: 单比特信号 "0!" 或 "1!"
// 格式2: 多比特信号 "b1010 !" // 格式2: 多比特信号 "b1010 !"
// 转义标识符中的特殊字符
const escapedId = signalDef.identifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
if (signalDef.width === 1) { if (signalDef.width === 1) {
// 单比特信号 // 单比特信号
const singleBitMatch = trimmedLine.match( const singleBitMatch = trimmedLine.match(
new RegExp(`^([01xz])${signalDef.identifier}$`) new RegExp(`^([01xz])${escapedId}$`)
); );
if (singleBitMatch) { if (singleBitMatch) {
values.push({ time: currentTime, value: singleBitMatch[1] }); values.push({ time: currentTime, value: singleBitMatch[1] });
@ -648,7 +728,7 @@ function parseVCDSignals(content: string, maxSignals: number = 3) {
} else { } else {
// 多比特信号 // 多比特信号
const multiBitMatch = trimmedLine.match( const multiBitMatch = trimmedLine.match(
new RegExp(`^b([01xz]+)\\s+${signalDef.identifier}$`) new RegExp(`^b([01xz]+)\\s+${escapedId}$`)
); );
if (multiBitMatch) { if (multiBitMatch) {
values.push({ time: currentTime, value: multiBitMatch[1] }); values.push({ time: currentTime, value: multiBitMatch[1] });
@ -661,12 +741,15 @@ function parseVCDSignals(content: string, maxSignals: number = 3) {
} }
} }
signals.push({ // 只添加有值变化数据的信号
name: signalDef.name, if (values.length > 0) {
identifier: signalDef.identifier, signals.push({
width: signalDef.width, name: signalDef.name,
values: values, identifier: signalDef.identifier,
}); width: signalDef.width,
values: values,
});
}
} }
} catch (error) { } catch (error) {
console.error("解析 VCD 信号数据失败:", error); console.error("解析 VCD 信号数据失败:", error);

View File

@ -59,7 +59,7 @@ export async function handleUserMessage(
text: string, text: string,
extensionPath?: string, extensionPath?: string,
mode?: RunMode, mode?: RunMode,
serviceTier?: ServiceTier // 新增:服务等级参数 serviceTier?: ServiceTier // 新增:服务等级参数
) { ) {
console.log("收到用户消息:", text); console.log("收到用户消息:", text);
@ -91,7 +91,14 @@ export async function handleUserMessage(
// 尝试使用后端服务 // 尝试使用后端服务
if (useBackendService && extensionPath) { if (useBackendService && extensionPath) {
try { try {
await handleUserMessageWithBackend(panel, text, extensionPath, mode, undefined, serviceTier); await handleUserMessageWithBackend(
panel,
text,
extensionPath,
mode,
undefined,
serviceTier
);
return; return;
} catch (error) { } catch (error) {
console.error("后端服务不可用:", error); console.error("后端服务不可用:", error);
@ -127,7 +134,7 @@ async function handleUserMessageWithBackend(
extensionPath: string, extensionPath: string,
mode?: RunMode, mode?: RunMode,
reuseTaskId?: string, // 可选,复用现有 taskId用于 Plan 模式确认后继续执行) reuseTaskId?: string, // 可选,复用现有 taskId用于 Plan 模式确认后继续执行)
serviceTier?: ServiceTier // 新增:服务等级参数 serviceTier?: ServiceTier // 新增:服务等级参数
): Promise<void> { ): Promise<void> {
const historyManager = ChatHistoryManager.getInstance(); const historyManager = ChatHistoryManager.getInstance();
@ -137,10 +144,18 @@ async function handleUserMessageWithBackend(
// 创建或复用会话 // 创建或复用会话
if (!currentSession || !currentSession.active) { if (!currentSession || !currentSession.active) {
currentSession = dialogManager.createSession(extensionPath, taskIdToUse || undefined); currentSession = dialogManager.createSession(
extensionPath,
taskIdToUse || undefined
);
// 保存 taskId 用于后续操作(如压缩) // 保存 taskId 用于后续操作(如压缩)
lastTaskId = currentSession.getTaskId(); lastTaskId = currentSession.getTaskId();
console.log("[MessageHandler] 创建会话: taskId=", lastTaskId, "来源=", taskIdToUse ? "historyManager" : "新生成"); console.log(
"[MessageHandler] 创建会话: taskId=",
lastTaskId,
"来源=",
taskIdToUse ? "historyManager" : "新生成"
);
} }
// 显示状态栏 // 显示状态栏
@ -290,7 +305,7 @@ async function handleUserMessageWithBackend(
}, },
}, },
mode, mode,
serviceTier // 传递服务等级 serviceTier // 传递服务等级
); );
}); });
} }

View File

@ -218,8 +218,16 @@ export function getWaveformPreviewScript(): string {
* 渲染波形预览信息 * 渲染波形预览信息
*/ */
function renderWaveformInfo(containerId, vcdInfo) { function renderWaveformInfo(containerId, vcdInfo) {
console.log('[renderWaveformInfo] 开始渲染波形, containerId:', containerId);
console.log('[renderWaveformInfo] vcdInfo:', vcdInfo);
const container = document.getElementById(containerId); const container = document.getElementById(containerId);
if (!container) return; if (!container) {
console.error('[renderWaveformInfo] 找不到容器:', containerId);
return;
}
console.log('[renderWaveformInfo] 找到容器,信号数量:', vcdInfo.signals?.length || 0);
// 清空容器 // 清空容器
container.innerHTML = ''; container.innerHTML = '';
@ -229,6 +237,7 @@ export function getWaveformPreviewScript(): string {
waveformSvg.innerHTML = drawRealWaveform(vcdInfo.signals || []); waveformSvg.innerHTML = drawRealWaveform(vcdInfo.signals || []);
container.appendChild(waveformSvg); container.appendChild(waveformSvg);
console.log('[renderWaveformInfo] 波形渲染完成');
} }
/** /**

View File

@ -632,6 +632,21 @@ export function getWebviewContent(
} }
break; break;
case 'checkPanelWidth':
// 检查面板宽度
const minWidth = message.minWidth || 200;
const currentWidth = document.body.clientWidth;
console.log('[WebView] 检查面板宽度:', currentWidth, '最小宽度:', minWidth);
if (currentWidth < minWidth) {
// 宽度不足,通知后端关闭面板
vscode.postMessage({
command: 'panelWidthInsufficient',
currentWidth: currentWidth,
minWidth: minWidth
});
}
break;
case 'vcdInfo': case 'vcdInfo':
// 渲染迷你波形预览信息 // 渲染迷你波形预览信息
try { try {
@ -742,6 +757,35 @@ export function getWebviewContent(
} }
}); });
// 监听窗口大小变化,检查面板宽度
let resizeTimer;
const MIN_PANEL_WIDTH = 500;
function checkPanelWidth() {
const currentWidth = document.body.clientWidth;
if (currentWidth < MIN_PANEL_WIDTH) {
console.log('[WebView] 面板宽度不足:', currentWidth, 'px最小要求:', MIN_PANEL_WIDTH, 'px');
vscode.postMessage({
command: 'panelWidthInsufficient',
currentWidth: currentWidth,
minWidth: MIN_PANEL_WIDTH
});
}
}
window.addEventListener('resize', () => {
// 使用防抖,避免频繁检查
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
checkPanelWidth();
}, 300);
});
// 初始加载时也检查一次
setTimeout(() => {
checkPanelWidth();
}, 500);
${getMessageAreaScript()} ${getMessageAreaScript()}
${getAgentCardScript()} ${getAgentCardScript()}
${getWaveformPreviewScript()} ${getWaveformPreviewScript()}