style: 优化界面样式和用户体验

- 调整工具调用显示的间距和字体大小
   - 优化低调工具调用的视觉效果
   - 改进整体界面的可读性
This commit is contained in:
Roe-xin
2026-02-26 21:44:58 +08:00
parent c3e3012a94
commit a479e81682
6 changed files with 90 additions and 51 deletions

View File

@ -6,8 +6,13 @@ import { VCDFileServer } from "../services/vcdFileServer";
/**
* VCD 波形查看器自定义编辑器提供者
*/
export class VCDViewerEditorProvider implements vscode.CustomReadonlyEditorProvider {
public static register(context: vscode.ExtensionContext, vcdFileServer: VCDFileServer): vscode.Disposable {
export class VCDViewerEditorProvider
implements vscode.CustomReadonlyEditorProvider
{
public static register(
context: vscode.ExtensionContext,
vcdFileServer: VCDFileServer,
): vscode.Disposable {
const provider = new VCDViewerEditorProvider(context, vcdFileServer);
const providerRegistration = vscode.window.registerCustomEditorProvider(
"ic-coder.vcdViewer",
@ -16,20 +21,20 @@ export class VCDViewerEditorProvider implements vscode.CustomReadonlyEditorProvi
webviewOptions: {
retainContextWhenHidden: true,
},
}
},
);
return providerRegistration;
}
constructor(
private readonly context: vscode.ExtensionContext,
private readonly vcdFileServer: VCDFileServer
private readonly vcdFileServer: VCDFileServer,
) {}
async openCustomDocument(
uri: vscode.Uri,
openContext: vscode.CustomDocumentOpenContext,
token: vscode.CancellationToken
token: vscode.CancellationToken,
): Promise<vscode.CustomDocument> {
return {
uri,
@ -40,7 +45,7 @@ export class VCDViewerEditorProvider implements vscode.CustomReadonlyEditorProvi
async resolveCustomEditor(
document: vscode.CustomDocument,
webviewPanel: vscode.WebviewPanel,
token: vscode.CancellationToken
token: vscode.CancellationToken,
): Promise<void> {
webviewPanel.webview.options = {
enableScripts: true,
@ -52,7 +57,7 @@ export class VCDViewerEditorProvider implements vscode.CustomReadonlyEditorProvi
webviewPanel,
this.context.extensionUri,
document.uri.fsPath,
this.vcdFileServer
this.vcdFileServer,
);
}
}
@ -68,7 +73,11 @@ export class VCDViewerPanel {
private _currentVcdPath: string | undefined;
private _vcdFileServer: VCDFileServer | undefined;
private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri, vcdFileServer?: VCDFileServer) {
private constructor(
panel: vscode.WebviewPanel,
extensionUri: vscode.Uri,
vcdFileServer?: VCDFileServer,
) {
this._panel = panel;
this._extensionUri = extensionUri;
this._vcdFileServer = vcdFileServer;
@ -91,7 +100,10 @@ export class VCDViewerPanel {
break;
case "loaded":
// Surfer iframe 加载完成,发送 VCD 文件
console.log("[VCDViewerPanel] Surfer 已加载,当前 VCD 路径:", this._currentVcdPath);
console.log(
"[VCDViewerPanel] Surfer 已加载,当前 VCD 路径:",
this._currentVcdPath,
);
if (this._currentVcdPath) {
this.sendVcdToSurfer(this._currentVcdPath);
}
@ -99,14 +111,18 @@ export class VCDViewerPanel {
}
},
null,
this._disposables
this._disposables,
);
}
/**
* 创建或显示 VCD 查看器面板
*/
public static createOrShow(extensionUri: vscode.Uri, vcdFilePath?: string, vcdFileServer?: VCDFileServer) {
public static createOrShow(
extensionUri: vscode.Uri,
vcdFilePath?: string,
vcdFileServer?: VCDFileServer,
) {
// 在当前活动编辑器旁边打开新列
const column = vscode.ViewColumn.Beside;
@ -128,10 +144,14 @@ export class VCDViewerPanel {
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [extensionUri],
}
},
);
VCDViewerPanel.currentPanel = new VCDViewerPanel(panel, extensionUri, vcdFileServer);
VCDViewerPanel.currentPanel = new VCDViewerPanel(
panel,
extensionUri,
vcdFileServer,
);
// 如果提供了 VCD 文件路径,加载它
if (vcdFilePath) {
@ -146,7 +166,7 @@ export class VCDViewerPanel {
panel: vscode.WebviewPanel,
extensionUri: vscode.Uri,
vcdFilePath: string,
vcdFileServer?: VCDFileServer
vcdFileServer?: VCDFileServer,
) {
const viewer = new VCDViewerPanel(panel, extensionUri, vcdFileServer);
viewer.loadVCDFile(vcdFilePath);
@ -172,14 +192,14 @@ export class VCDViewerPanel {
// 更新面板标题
const fileName = path.basename(vcdFilePath);
this._panel.title = `Surfer 波形查看器 - ${fileName}`;
this._panel.title = `波形查看器 - ${fileName}`;
// 设置 HTML 内容
this._panel.webview.html = this._getWebviewContent();
console.log("[VCDViewerPanel] Webview HTML 已设置");
} catch (error) {
vscode.window.showErrorMessage(
`加载 VCD 文件失败: ${error instanceof Error ? error.message : "未知错误"}`
`加载 VCD 文件失败: ${error instanceof Error ? error.message : "未知错误"}`,
);
}
}
@ -190,8 +210,8 @@ export class VCDViewerPanel {
private parseVcdRootScope(vcdFilePath: string): string[] {
try {
// 读取 VCD 文件
const buffer = fs.readFileSync(vcdFilePath, { encoding: 'utf8' });
const lines = buffer.split('\n');
const buffer = fs.readFileSync(vcdFilePath, { encoding: "utf8" });
const lines = buffer.split("\n");
const scopeNames: string[] = [];
let scopeDepth = 0;
@ -201,7 +221,7 @@ export class VCDViewerPanel {
const trimmed = line.trim();
// 遇到 $enddefinitions 就停止解析
if (trimmed.startsWith('$enddefinitions')) {
if (trimmed.startsWith("$enddefinitions")) {
break;
}
@ -212,22 +232,22 @@ export class VCDViewerPanel {
const scopeName = scopeMatch[2];
// 记录顶层 module (depth = 0)
if (scopeDepth === 0 && scopeType === 'module') {
if (scopeDepth === 0 && scopeType === "module") {
scopeStack.push(scopeName);
console.log("[VCDViewerPanel] 找到顶层作用域:", scopeName);
}
// 记录顶层下的直接子模块 (depth = 1)
else if (scopeDepth === 1 && scopeType === 'module') {
else if (scopeDepth === 1 && scopeType === "module") {
const fullPath = [...scopeStack, scopeName];
scopeNames.push(fullPath.join('.'));
console.log("[VCDViewerPanel] 找到子模块:", fullPath.join('.'));
scopeNames.push(fullPath.join("."));
console.log("[VCDViewerPanel] 找到子模块:", fullPath.join("."));
}
scopeDepth++;
}
// 遇到 $upscope 减少深度
if (trimmed.startsWith('$upscope')) {
if (trimmed.startsWith("$upscope")) {
scopeDepth--;
if (scopeDepth === 0) {
scopeStack.pop();
@ -277,7 +297,7 @@ export class VCDViewerPanel {
} catch (error) {
console.error("[VCDViewerPanel] 发送 VCD 数据失败:", error);
vscode.window.showErrorMessage(
`发送 VCD 数据失败: ${error instanceof Error ? error.message : "未知错误"}`
`发送 VCD 数据失败: ${error instanceof Error ? error.message : "未知错误"}`,
);
}
}
@ -352,13 +372,23 @@ export class VCDViewerPanel {
private _getWebviewContent(): string {
// 获取 surfer 资源 URI
const surferJsUri = this._panel.webview.asWebviewUri(
vscode.Uri.joinPath(this._extensionUri, "media", "surfer", "surfer.js")
vscode.Uri.joinPath(this._extensionUri, "media", "surfer", "surfer.js"),
);
const surferWasmUri = this._panel.webview.asWebviewUri(
vscode.Uri.joinPath(this._extensionUri, "media", "surfer", "surfer_bg.wasm")
vscode.Uri.joinPath(
this._extensionUri,
"media",
"surfer",
"surfer_bg.wasm",
),
);
const integrationJsUri = this._panel.webview.asWebviewUri(
vscode.Uri.joinPath(this._extensionUri, "media", "surfer", "integration.js")
vscode.Uri.joinPath(
this._extensionUri,
"media",
"surfer",
"integration.js",
),
);
return `<!DOCTYPE html>
@ -367,7 +397,7 @@ export class VCDViewerPanel {
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline' 'unsafe-eval' ${this._panel.webview.cspSource}; worker-src blob:; connect-src ${this._panel.webview.cspSource} blob: http://127.0.0.1:*;">
<title>Surfer 波形查看器</title>
<title>波形查看器</title>
<script>
// 获取 VS Code API只能调用一次

View File

@ -5,7 +5,7 @@ import * as vscode from "vscode";
/**
* VCD 文件 HTTP 服务器
* 用于为 Surfer 波形查看器提供 VCD 文件访问
* 用于为 波形查看器提供 VCD 文件访问
*/
export class VCDFileServer {
private server: http.Server | null = null;
@ -98,7 +98,10 @@ export class VCDFileServer {
/**
* 处理 HTTP 请求
*/
private handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
private handleRequest(
req: http.IncomingMessage,
res: http.ServerResponse,
): void {
const url = req.url || "";
console.log(`[VCDFileServer] 收到请求: ${url}`);
@ -214,7 +217,12 @@ export class VCDFileServer {
}
const fileName = match[1];
const filePath = path.join(this.extensionUri.fsPath, "media", "surfer", fileName);
const filePath = path.join(
this.extensionUri.fsPath,
"media",
"surfer",
fileName,
);
if (!fs.existsSync(filePath)) {
console.error(`[VCDFileServer] 静态文件不存在: ${filePath}`);
@ -257,8 +265,8 @@ export class VCDFileServer {
*/
private parseVcdRootScope(vcdFilePath: string): string[] {
try {
const buffer = fs.readFileSync(vcdFilePath, { encoding: 'utf8' });
const lines = buffer.split('\n');
const buffer = fs.readFileSync(vcdFilePath, { encoding: "utf8" });
const lines = buffer.split("\n");
const scopeNames: string[] = [];
let scopeDepth = 0;
@ -267,7 +275,7 @@ export class VCDFileServer {
for (const line of lines) {
const trimmed = line.trim();
if (trimmed.startsWith('$enddefinitions')) {
if (trimmed.startsWith("$enddefinitions")) {
break;
}
@ -276,17 +284,17 @@ export class VCDFileServer {
const scopeType = scopeMatch[1];
const scopeName = scopeMatch[2];
if (scopeDepth === 0 && scopeType === 'module') {
if (scopeDepth === 0 && scopeType === "module") {
scopeStack.push(scopeName);
} else if (scopeDepth === 1 && scopeType === 'module') {
} else if (scopeDepth === 1 && scopeType === "module") {
const fullPath = [...scopeStack, scopeName];
scopeNames.push(fullPath.join('.'));
scopeNames.push(fullPath.join("."));
}
scopeDepth++;
}
if (trimmed.startsWith('$upscope')) {
if (trimmed.startsWith("$upscope")) {
scopeDepth--;
if (scopeDepth === 0) {
scopeStack.pop();
@ -323,7 +331,7 @@ export class VCDFileServer {
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Surfer 波形查看器 - ${fileName}</title>
<title>波形查看器 - ${fileName}</title>
<script>
window.surferReady = false;
window.pendingVcdData = null;

View File

@ -38,6 +38,7 @@ export function getAgentCardStyles(): string {
.agent-name {
font-weight: 500;
flex: 1;
font-size:14px
}
.agent-status {
font-size: 11px;
@ -99,14 +100,14 @@ export function getAgentCardStyles(): string {
/* 低调显示的工具调用样式 */
.agent-step.low-profile {
opacity: 0.85;
font-size: 12px;
font-size: 13px;
padding: 4px 8px;
background: transparent;
margin-bottom: 2px;
}
.agent-step.low-profile .step-icon {
opacity: 0.8;
font-size: 12px;
font-size: 13px;
}
.agent-step.low-profile .step-name {
font-weight: 400;
@ -115,7 +116,7 @@ export function getAgentCardStyles(): string {
}
.agent-step.low-profile .step-result {
opacity: 0.85;
font-size: 11px;
font-size: 12px;
}
`;
}

View File

@ -41,18 +41,18 @@ export function getContextButtonContent(): string {
<path d="M340.864 149.312l384 384-384 384-45.248-45.248L634.368 533.312 295.616 194.56z" fill="currentColor"/>
</svg>
</div>
<div class="context-menu-item" onclick="handleAddImage()">
<!-- <div class="context-menu-item" onclick="handleAddImage()">
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<path d="M928 160H96c-17.7 0-32 14.3-32 32v640c0 17.7 14.3 32 32 32h832c17.7 0 32-14.3 32-32V192c0-17.7-14.3-32-32-32z m-40 632H136V232h752v560z m-120-240c0 55.2-44.8 100-100 100s-100-44.8-100-100 44.8-100 100-100 100 44.8 100 100z m-476 0l164 164h476L696 480 536 640l-84-84-160 160z" fill="currentColor"/>
</svg>
<span>图片</span>
</div>
<div class="context-menu-item" onclick="handleAddDocument()">
</div> -->
<!-- <div class="context-menu-item" onclick="handleAddDocument()">
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<path d="M832 64H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32z m-40 824H232V136h560v752z m-120-568H352c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h320c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z m0 144H352c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h320c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z m0 144H352c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h320c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8z" fill="currentColor"/>
</svg>
<span>文档库</span>
</div>
</div> -->
</div>
<!-- 文件/文件夹列表视图 -->

View File

@ -380,7 +380,7 @@ export function getMessageAreaStyles(): string {
}
/* 低调显示的工具调用 - 移除边距和背景 */
.segment-tool.low-profile {
margin: 2px 0px;
margin: 5px 0px;
padding: 0;
background: none;
}
@ -545,7 +545,7 @@ export function getMessageAreaStyles(): string {
}
.tool-segment-description {
margin: 6px 0 0 0px;
font-size: 12px;
font-size: 0.9rem;
color: #ccc;
line-height: 1.4;
}
@ -564,7 +564,7 @@ export function getMessageAreaStyles(): string {
}
.segment-tool.low-profile .tool-segment-result {
opacity: 0.7;
font-size: 10px;
font-size: 12px;
}
.segment-question {
background: var(--vscode-textBlockQuote-background);

View File

@ -304,6 +304,7 @@ export function getWebviewContent(
}
.segment-text {
line-height: 1.6;
font-size:0.9rem
}
.segment-tool {
background: var(--vscode-textBlockQuote-background);
@ -325,7 +326,6 @@ export function getWebviewContent(
color: var(--vscode-foreground);
}
.tool-segment-result {
margin-top: 6px;
font-size: 12px;
color: var(--vscode-descriptionForeground);
padding-left: 22px;