feat: 终端空闲状态优化 — ASCII Logo + 工作空间信息 + 轮转贴士

This commit is contained in:
thzxx
2026-04-19 19:35:24 +08:00
parent 8d03f42611
commit 2134e1be38
2 changed files with 177 additions and 1 deletions
+94 -1
View File
@@ -47,6 +47,22 @@ let fileTree: FileNode[] = [];
let previewFile: { name: string; content: string; path: string } | null = null;
let _counter = 0;
// ── 空闲状态轮转贴士 ──
const IDLE_TIPS = [
'💡 可以让我读取文件、搜索代码、执行命令',
'💡 试试说"帮我看看这个目录里有什么"',
'💡 我可以联网搜索并抓取网页内容',
'💡 支持 Git 操作:状态查看、提交、分支管理',
'💡 我能记住你说过的重要信息,跨会话保留',
'💡 上传图片让我分析,支持 Vision 模型',
'💡 说"搜索..."我会自动联网查找最新信息',
'💡 我会从成功经验中学习,越用越聪明',
'💡 可以让我对比文件差异、批量替换文本',
'💡 支持浏览器控制,帮你操作网页',
];
let tipIndex = Math.floor(Math.random() * IDLE_TIPS.length);
let tipTimer: ReturnType<typeof setInterval> | null = null;
/** 工具调用卡片列表 */
let toolCards: ToolCallRecord[] = [];
let toolAutoScroll = true;
@@ -491,8 +507,17 @@ function renderTerminal(): void {
return;
}
// 空闲状态:显示 Logo + 信息 + 贴士
if (session.lines.length === 0 && !session.running) {
renderIdleState(container);
startTipRotation(container);
return;
}
// 有内容时停止贴士轮转
stopTipRotation();
// 使用 DocumentFragment 优化渲染
const fragment = document.createDocumentFragment();
const wrapper = document.createElement('div');
for (const line of session.lines) {
@@ -516,6 +541,74 @@ function renderTerminal(): void {
};
}
/** 渲染空闲状态 */
function renderIdleState(container: HTMLElement): void {
const tip = IDLE_TIPS[tipIndex];
const dirDisplay = workspaceDir
? workspaceDir.replace(/.*[/\\]/, '~/.')
: '未设置';
// 截取目录最后一段
const shortDir = workspaceDir
? '...' + workspaceDir.slice(-30)
: '未设置';
container.innerHTML = `
<div class="ws-idle-state">
<div class="ws-idle-logo">
<pre class="ws-idle-ascii"> ╭───────╮
│ ◕ ◕ │
│ ▽ │
╰─┬───┬─╯
╱│ │╲
│ │ ╲
🦙 Metona</pre>
</div>
<div class="ws-idle-info">
<div class="ws-idle-info-row">
<span class="ws-idle-label">工作空间</span>
<span class="ws-idle-value" title="${escapeHtml(workspaceDir)}">${escapeHtml(shortDir)}</span>
</div>
</div>
<div class="ws-idle-divider"></div>
<div class="ws-idle-tip" id="wsIdleTip">${escapeHtml(tip)}</div>
</div>
`;
// 重置滚动
container.scrollTop = 0;
}
/** 启动贴士轮转 */
function startTipRotation(container: HTMLElement): void {
if (tipTimer) return;
tipTimer = setInterval(() => {
// 只在空闲状态时轮转
const session = getActiveSession();
if (!session || session.lines.length > 0 || session.running) {
stopTipRotation();
return;
}
tipIndex = (tipIndex + 1) % IDLE_TIPS.length;
const tipEl = container.querySelector('#wsIdleTip');
if (tipEl) {
tipEl.classList.add('fading');
setTimeout(() => {
tipEl.textContent = IDLE_TIPS[tipIndex];
tipEl.classList.remove('fading');
}, 300);
}
}, 6000);
}
/** 停止贴士轮转 */
function stopTipRotation(): void {
if (tipTimer) {
clearInterval(tipTimer);
tipTimer = null;
}
}
function renderFileList(): void {
const container = document.querySelector('#wsFileList') as HTMLElement;
if (!container) return;