Files
esengine/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/template/debug/index.html
2025-06-17 07:35:23 +08:00

382 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="debug-panel">
<!-- 顶部控制栏 -->
<div class="debug-toolbar">
<div class="toolbar-section">
<label>游戏实例:</label>
<select v-model="selectedInstanceId" @change="onInstanceChanged" class="instance-selector">
<option value="">-- 选择实例 --</option>
<option v-for="instance in gameInstances" :key="instance.id" :value="instance.id">
{{ instance.name }} ({{ instance.isActive ? '活跃' : '离线' }})
</option>
</select>
<span class="instance-count">{{ gameInstances.length }} 个实例</span>
</div>
<div class="toolbar-section">
<button @click="manualRefresh" class="btn-refresh" :disabled="!selectedInstanceId">
<ui-icon value="refresh"></ui-icon>
刷新
</button>
<label class="checkbox-label">
<input type="checkbox" v-model="isAutoRefresh" @change="toggleAutoRefresh">
自动刷新
</label>
<select v-model="refreshInterval" @change="changeRefreshInterval" :disabled="!isAutoRefresh">
<option :value="100">0.1秒</option>
<option :value="250">0.25秒</option>
<option :value="500">0.5秒</option>
<option :value="1000">1秒</option>
<option :value="2000">2秒</option>
</select>
</div>
<div class="toolbar-section">
<span class="last-update">{{ lastUpdateTime }}</span>
</div>
</div>
<!-- 连接状态和基础信息 -->
<div class="debug-section">
<div class="section-header">
<h2>📊 实例状态</h2>
</div>
<div class="status-grid" v-if="selectedInstanceId && debugInfo.instanceId">
<div class="status-item">
<span class="label">实例名称:</span>
<span class="value">{{ debugInfo.instanceName }}</span>
</div>
<div class="status-item">
<span class="label">运行状态:</span>
<span class="value" :class="{ online: debugInfo.isRunning, offline: !debugInfo.isRunning }">
{{ debugInfo.isRunning ? '运行中' : '已停止' }}
</span>
</div>
<div class="status-item">
<span class="label">当前场景:</span>
<span class="value">{{ debugInfo.currentScene }}</span>
</div>
<div class="status-item">
<span class="label">运行时间:</span>
<span class="value">{{ formatUptime(debugInfo.uptime) }}</span>
</div>
</div>
<div class="no-instance" v-else>
<ui-icon value="info" class="info-icon"></ui-icon>
<span>请选择一个游戏实例查看详细信息</span>
</div>
</div>
<!-- 性能监控 -->
<div class="debug-section" v-if="debugInfo.instanceId">
<div class="section-header">
<h2>⚡ 性能监控</h2>
</div>
<div class="performance-grid">
<div class="perf-card">
<div class="perf-title">帧率</div>
<div class="perf-value" :class="getFpsColor(debugInfo.performance.fps)">
{{ debugInfo.performance.fps }} FPS
</div>
<div class="perf-detail">
引擎帧时间: {{ debugInfo.performance.engineFrameTime?.toFixed(2) || '0.00' }}ms
</div>
</div>
<div class="perf-card">
<div class="perf-title">ECS执行时间</div>
<div class="perf-value" :class="getECSTimeColor(debugInfo.performance.ecsPercentage)">
{{ debugInfo.performance.frameTime.toFixed(3) }}ms
</div>
<div class="perf-detail">
占总帧时间: {{ debugInfo.performance.ecsPercentage?.toFixed(1) || '0.0' }}%
</div>
</div>
<div class="perf-card">
<div class="perf-title">总内存</div>
<div class="perf-value" :class="getMemoryColor(debugInfo.memory.usedMemory / debugInfo.memory.totalMemory * 100)">
{{ formatMemory(debugInfo.memory.usedMemory) }}
</div>
<div class="perf-detail">
/ {{ formatMemory(debugInfo.memory.totalMemory) }}
</div>
</div>
<div class="perf-card">
<div class="perf-title">GC回收</div>
<div class="perf-value">{{ debugInfo.memory.gcCollections }}</div>
<div class="perf-detail">次数</div>
</div>
</div>
</div>
<!-- 内存分析 -->
<div class="debug-section" v-if="debugInfo.instanceId">
<div class="section-header">
<h2>💾 内存分析</h2>
</div>
<div class="memory-breakdown">
<div class="memory-item">
<span class="memory-label">实体内存:</span>
<span class="memory-value">{{ formatMemory(debugInfo.memory.entityMemory) }}</span>
<div class="memory-bar">
<div class="memory-fill" :style="{ width: (debugInfo.memory.entityMemory / debugInfo.memory.usedMemory * 100) + '%' }"></div>
</div>
</div>
<div class="memory-item">
<span class="memory-label">组件内存:</span>
<span class="memory-value">{{ formatMemory(debugInfo.memory.componentMemory) }}</span>
<div class="memory-bar">
<div class="memory-fill" :style="{ width: (debugInfo.memory.componentMemory / debugInfo.memory.usedMemory * 100) + '%' }"></div>
</div>
</div>
<div class="memory-item">
<span class="memory-label">系统内存:</span>
<span class="memory-value">{{ formatMemory(debugInfo.memory.systemMemory) }}</span>
<div class="memory-bar">
<div class="memory-fill" :style="{ width: (debugInfo.memory.systemMemory / debugInfo.memory.usedMemory * 100) + '%' }"></div>
</div>
</div>
<div class="memory-item">
<span class="memory-label">对象池内存:</span>
<span class="memory-value">{{ formatMemory(debugInfo.memory.pooledMemory) }}</span>
<div class="memory-bar">
<div class="memory-fill" :style="{ width: (debugInfo.memory.pooledMemory / debugInfo.memory.usedMemory * 100) + '%' }"></div>
</div>
</div>
</div>
</div>
<!-- 实体统计 -->
<div class="debug-section" v-if="debugInfo.instanceId">
<div class="section-header">
<h2>👥 实体统计</h2>
</div>
<div class="entity-stats">
<div class="stat-card">
<div class="stat-number">{{ debugInfo.entities.total }}</div>
<div class="stat-label">总实体数</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ debugInfo.entities.active }}</div>
<div class="stat-label">活跃实体</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ debugInfo.entities.inactive }}</div>
<div class="stat-label">非活跃实体</div>
</div>
<div class="stat-card">
<div class="stat-number">{{ debugInfo.entities.pendingAdd }}</div>
<div class="stat-label">待添加</div>
</div>
</div>
<!-- Archetype分布 -->
<div class="archetype-section" v-if="debugInfo.entities.entitiesPerArchetype.length > 0">
<h3>Archetype 分布</h3>
<div class="archetype-list">
<div v-for="archetype in debugInfo.entities.entitiesPerArchetype" :key="archetype.signature" class="archetype-item">
<div class="archetype-signature">{{ archetype.signature }}</div>
<div class="archetype-stats">
<span class="entity-count">{{ archetype.count }} 实体</span>
<span class="memory-usage">{{ formatMemory(archetype.memory) }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- 组件分析 -->
<div class="debug-section" v-if="debugInfo.instanceId">
<div class="section-header">
<h2>🧩 组件分析</h2>
<div class="section-help">
<button class="help-btn" @click="showComponentPoolHelp = !showComponentPoolHelp" title="组件对象池使用说明">
<ui-icon value="help"></ui-icon>
对象池使用说明
</button>
</div>
</div>
<!-- 对象池使用说明 -->
<div v-if="showComponentPoolHelp" class="help-panel">
<div class="help-content">
<h4>📖 组件对象池使用指南</h4>
<p>组件对象池用于复用组件实例,减少频繁创建/销毁组件带来的内存分配开销。当前利用率为0表示还未配置对象池。</p>
<div class="help-steps">
<div class="help-step">
<h5>1. 注册组件对象池</h5>
<pre class="code-example">import { ComponentPoolManager } from '@esengine/ecs-framework';
// 为Transform组件注册对象池
ComponentPoolManager.getInstance().registerPool(
'Transform',
() => new Transform(),
(comp) => comp.reset(), // 可选的重置函数
100 // 池大小
);</pre>
</div>
<div class="help-step">
<h5>2. 使用对象池获取组件</h5>
<pre class="code-example">// 从对象池获取组件实例
const poolManager = ComponentPoolManager.getInstance();
const transform = poolManager.acquireComponent('Transform');
// 使用完毕后释放回池中
poolManager.releaseComponent('Transform', transform);</pre>
</div>
<div class="help-step">
<h5>3. 查看性能改进</h5>
<p>正确配置后利用率栏将显示池的使用情况。利用率越高说明对象池被有效使用可以减少GC压力。</p>
</div>
</div>
<div class="help-links">
<a href="#" @click="openDocumentation('component-pool')" class="doc-link">
<ui-icon value="book"></ui-icon>
查看详细文档
</a>
<a href="#" @click="openDocumentation('performance-optimization')" class="doc-link">
<ui-icon value="speed"></ui-icon>
性能优化指南
</a>
</div>
<div class="doc-access-note">
<ui-icon value="info"></ui-icon>
<span>如果无法直接打开文档链接,链接将自动复制到剪贴板,请在浏览器中粘贴访问</span>
</div>
</div>
</div>
<div class="component-overview">
<div class="overview-item">
<span class="label">组件类型:</span>
<span class="value">{{ debugInfo.components.totalTypes }}</span>
</div>
<div class="overview-item">
<span class="label">组件实例:</span>
<span class="value">{{ debugInfo.components.totalInstances }}</span>
</div>
</div>
<div class="component-table" v-if="debugInfo.components.componentStats.length > 0">
<div class="table-header">
<div class="col-name">组件类型</div>
<div class="col-count">实例数</div>
<div class="col-memory">内存占用</div>
<div class="col-pool">对象池</div>
<div class="col-efficiency">
利用率
<span class="help-tooltip" title="对象池利用率:使用中的实例 / 池总大小。利用率为0表示未配置对象池">
<ui-icon value="help"></ui-icon>
</span>
</div>
</div>
<div v-for="comp in debugInfo.components.componentStats" :key="comp.typeName" class="table-row">
<div class="col-name">{{ comp.typeName }}</div>
<div class="col-count">{{ comp.instanceCount }}</div>
<div class="col-memory">{{ formatMemory(comp.totalMemory) }}</div>
<div class="col-pool">
{{ comp.poolSize || '未配置' }}
<span v-if="comp.poolSize === 0" class="not-configured" title="点击上方说明了解如何配置对象池">
<ui-icon value="warning"></ui-icon>
</span>
</div>
<div class="col-efficiency">
<div class="efficiency-bar">
<div class="efficiency-fill" :style="{ width: comp.poolUtilization + '%' }"></div>
</div>
{{ comp.poolUtilization.toFixed(1) }}%
<span v-if="comp.poolUtilization === 0 && comp.poolSize === 0" class="no-pool-hint">
(无对象池)
</span>
</div>
</div>
</div>
<!-- 无对象池组件提示 -->
<div v-if="debugInfo.components.componentStats.length > 0 && debugInfo.components.componentStats.every(c => c.poolSize === 0)" class="pool-suggestion">
<div class="suggestion-content">
<ui-icon value="lightbulb" class="suggestion-icon"></ui-icon>
<div class="suggestion-text">
<h4>💡 性能优化建议</h4>
<p>检测到所有组件都未配置对象池。为频繁创建/销毁的组件配置对象池可以显著提升性能,减少垃圾回收压力。</p>
<button @click="showComponentPoolHelp = true" class="suggestion-action">
了解如何配置对象池
</button>
</div>
</div>
</div>
</div>
<!-- 系统性能 -->
<div class="debug-section" v-if="debugInfo.instanceId">
<div class="section-header">
<h2>⚙️ 系统性能</h2>
</div>
<div class="systems-table" v-if="debugInfo.systems.systemStats.length > 0">
<div class="table-header">
<div class="col-name">系统名称</div>
<div class="col-entities">实体数</div>
<div class="col-time">执行时间</div>
<div class="col-percentage">ECS占比</div>
<div class="col-order">优先级</div>
<div class="col-status">状态</div>
</div>
<div v-for="system in debugInfo.systems.systemStats" :key="system.name" class="table-row">
<div class="col-name">{{ system.name }}</div>
<div class="col-entities">{{ system.entityCount }}</div>
<div class="col-time">
<span :class="getExecutionTimeColor(system.averageExecutionTime)">
{{ system.averageExecutionTime.toFixed(3) }}ms
</span>
<div class="time-range">
({{ system.minExecutionTime.toFixed(3) }}-{{ system.maxExecutionTime.toFixed(3) }}ms)
</div>
</div>
<div class="col-percentage">
<div class="percentage-bar">
<div class="percentage-fill" :style="{ width: (system.percentage || 0) + '%' }"></div>
</div>
{{ (system.percentage || 0).toFixed(1) }}%
</div>
<div class="col-order">{{ system.updateOrder }}</div>
<div class="col-status">
<span :class="{ enabled: system.enabled, disabled: !system.enabled }">
{{ system.enabled ? '启用' : '禁用' }}
</span>
</div>
</div>
</div>
</div>
<!-- 服务器状态 -->
<div class="debug-section" v-if="gameInstances.length === 0">
<div class="section-header">
<h2>🔌 调试服务器</h2>
</div>
<div class="server-status">
<div class="status-message">
<ui-icon value="wifi" class="server-icon"></ui-icon>
<div class="message-content">
<h3>等待游戏实例连接...</h3>
<p>调试服务器正在 <strong>ws://localhost:8080</strong> 监听连接</p>
<p>请确保游戏中的ECS框架已启用调试模式</p>
</div>
</div>
<div class="connection-help">
<h4>连接说明:</h4>
<ul>
<li>在ECSManager组件中启用调试模式</li>
<li>运行游戏,框架会自动连接到调试服务器</li>
<li>支持多个游戏实例同时连接</li>
<li>可以在上方选择不同的实例进行调试</li>
</ul>
</div>
</div>
</div>
</div>
</div>