feat: TypeScript + Electron v2 重构 - 纯桌面版
- 全面迁移到 TypeScript,严格类型定义 - 放弃 Web 版,专注 Electron 桌面应用 - 主进程模块化:main.ts, preload.ts, menu.ts, tray.ts, ipc.ts, utils.ts - 渲染进程完整迁移所有功能组件 - 删除 PWA 相关文件 (sw.js, manifest.json) - 删除 Web 版降级逻辑 - 保留所有核心功能:流式对话、多模型、Think推理、多模态、RAG知识库、Agent预设、历史管理 - 保留 Windows 11 Fluent Design 暗色主题样式
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Header - 顶部导航组件
|
||||
*/
|
||||
|
||||
import { state, KEYS } from '../state/state.js';
|
||||
import { formatSize } from '../utils/utils.js';
|
||||
import { OllamaAPI } from '../api/ollama.js';
|
||||
|
||||
let connStatusEl: HTMLElement;
|
||||
|
||||
export function initHeader(): void {
|
||||
connStatusEl = document.querySelector('#connStatus')!;
|
||||
}
|
||||
|
||||
export async function checkConnection(): Promise<{ ok: boolean; version?: { version: string }; error?: Error }> {
|
||||
const api = state.get<OllamaAPI>(KEYS.API);
|
||||
if (!api) return { ok: false, error: new Error('API 未初始化') };
|
||||
|
||||
connStatusEl.className = 'conn-status pending';
|
||||
connStatusEl.querySelector('.status-label')!.textContent = '连接中...';
|
||||
|
||||
try {
|
||||
const version = await api.getVersion();
|
||||
connStatusEl.className = 'conn-status connected';
|
||||
connStatusEl.title = `已连接 (v${version.version})`;
|
||||
connStatusEl.querySelector('.status-label')!.textContent = '已连接';
|
||||
return { ok: true, version };
|
||||
} catch (err) {
|
||||
connStatusEl.className = 'conn-status disconnected';
|
||||
connStatusEl.title = '未连接';
|
||||
connStatusEl.querySelector('.status-label')!.textContent = '未连接';
|
||||
return { ok: false, error: err as Error };
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateConnectionInfo(): Promise<void> {
|
||||
const api = state.get<OllamaAPI>(KEYS.API);
|
||||
if (!api) return;
|
||||
|
||||
const badge = document.querySelector('#connBadge')!;
|
||||
const verEl = document.querySelector('#serverVersion')!;
|
||||
const corsHint = document.querySelector('#corsHint') as HTMLElement;
|
||||
|
||||
badge.textContent = '检测中...';
|
||||
badge.className = 'status-badge warning';
|
||||
verEl.textContent = '';
|
||||
|
||||
try {
|
||||
const version = await api.getVersion();
|
||||
badge.textContent = '✓ 已连接';
|
||||
badge.className = 'status-badge success';
|
||||
verEl.textContent = `v${version.version}`;
|
||||
corsHint.style.display = 'none';
|
||||
} catch (err) {
|
||||
badge.textContent = '✗ 未连接';
|
||||
badge.className = 'status-badge error';
|
||||
verEl.textContent = '';
|
||||
|
||||
if ((err as Error).message.includes('Failed to fetch') || (err as Error).message.includes('NetworkError') || (err as Error).message.includes('CORS')) {
|
||||
corsHint.style.display = '';
|
||||
} else {
|
||||
corsHint.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateRunningModels(): Promise<void> {
|
||||
const api = state.get<OllamaAPI>(KEYS.API);
|
||||
if (!api) return;
|
||||
|
||||
const container = document.querySelector('#runningModels')!;
|
||||
try {
|
||||
const data = await api.psModels();
|
||||
if (!data.models || data.models.length === 0) {
|
||||
container.innerHTML = '<p class="text-muted">无运行中的模型</p>';
|
||||
return;
|
||||
}
|
||||
container.innerHTML = data.models.map(m => `
|
||||
<div class="running-model">
|
||||
<span class="model-name">${m.name}</span>
|
||||
<span class="model-vram">${formatSize(m.size_vram || 0)} VRAM</span>
|
||||
</div>
|
||||
`).join('');
|
||||
} catch {
|
||||
container.innerHTML = '<p class="text-muted">无法获取运行信息</p>';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user