mirror of
https://github.com/Xe138/AI-Trader.git
synced 2026-04-05 18:27:25 -04:00
update frontend
This commit is contained in:
@@ -375,6 +375,12 @@ body {
|
||||
background: rgba(0, 212, 255, 0.1);
|
||||
}
|
||||
|
||||
.legend-icon-img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.legend-color {
|
||||
width: 4px;
|
||||
height: 42px;
|
||||
|
||||
@@ -18,6 +18,27 @@ const agentColors = [
|
||||
'#06ffa5' // Mint
|
||||
];
|
||||
|
||||
// Cache for loaded SVG images
|
||||
const iconImageCache = {};
|
||||
|
||||
// Function to load SVG as image
|
||||
function loadIconImage(iconPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (iconImageCache[iconPath]) {
|
||||
resolve(iconImageCache[iconPath]);
|
||||
return;
|
||||
}
|
||||
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
iconImageCache[iconPath] = img;
|
||||
resolve(img);
|
||||
};
|
||||
img.onerror = reject;
|
||||
img.src = iconPath;
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize the page
|
||||
async function init() {
|
||||
showLoading();
|
||||
@@ -28,6 +49,17 @@ async function init() {
|
||||
allAgentsData = await dataLoader.loadAllAgentsData();
|
||||
console.log('Data loaded:', allAgentsData);
|
||||
|
||||
// Preload all agent icons
|
||||
const agentNames = Object.keys(allAgentsData);
|
||||
const iconPromises = agentNames.map(agentName => {
|
||||
const iconPath = dataLoader.getAgentIcon(agentName);
|
||||
return loadIconImage(iconPath).catch(err => {
|
||||
console.warn(`Failed to load icon for ${agentName}:`, err);
|
||||
});
|
||||
});
|
||||
await Promise.all(iconPromises);
|
||||
console.log('Icons preloaded');
|
||||
|
||||
// Update stats
|
||||
updateStats();
|
||||
|
||||
@@ -171,11 +203,7 @@ function createChart() {
|
||||
const x = lastPoint.x;
|
||||
const y = lastPoint.y;
|
||||
|
||||
// Draw icon
|
||||
ctx.save();
|
||||
ctx.font = 'bold 22px Arial';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
// Draw background circle with glow
|
||||
const iconSize = 30;
|
||||
@@ -191,9 +219,12 @@ function createChart() {
|
||||
// Reset shadow
|
||||
ctx.shadowBlur = 0;
|
||||
|
||||
// Draw icon
|
||||
ctx.fillStyle = '#0a0e27';
|
||||
ctx.fillText(dataset.agentIcon, x + 22 - 9, y);
|
||||
// Draw icon image if loaded
|
||||
if (iconImageCache[dataset.agentIcon]) {
|
||||
const img = iconImageCache[dataset.agentIcon];
|
||||
const imgSize = iconSize * 0.6; // Icon slightly smaller than circle
|
||||
ctx.drawImage(img, x + 22 - imgSize/2, y - imgSize/2, imgSize, imgSize);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
@@ -242,8 +273,8 @@ function createChart() {
|
||||
label: function(context) {
|
||||
const label = context.dataset.label || '';
|
||||
const value = dataLoader.formatCurrency(context.parsed.y);
|
||||
const icon = context.dataset.agentIcon || '';
|
||||
return `${icon} ${label}: ${value}`;
|
||||
// Tooltips don't support images, so just show label and value
|
||||
return `${label}: ${value}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,13 +342,15 @@ function createLegend() {
|
||||
|
||||
const returnValue = data.return;
|
||||
const returnClass = returnValue >= 0 ? 'positive' : 'negative';
|
||||
const icon = dataLoader.getAgentIcon(agentName);
|
||||
const iconPath = dataLoader.getAgentIcon(agentName);
|
||||
const brandColor = dataLoader.getAgentBrandColor(agentName);
|
||||
|
||||
const legendItem = document.createElement('div');
|
||||
legendItem.className = 'legend-item';
|
||||
legendItem.innerHTML = `
|
||||
<div class="legend-icon" ${brandColor ? `style="background: ${brandColor}20; color: ${brandColor};"` : ''}>${icon}</div>
|
||||
<div class="legend-icon" ${brandColor ? `style="background: ${brandColor}20;"` : ''}>
|
||||
<img src="${iconPath}" alt="${agentName}" class="legend-icon-img" />
|
||||
</div>
|
||||
<div class="legend-color" style="background: ${color}; border-style: ${borderStyle};"></div>
|
||||
<div class="legend-info">
|
||||
<div class="legend-name">${dataLoader.getAgentDisplayName(agentName)}</div>
|
||||
|
||||
@@ -359,17 +359,28 @@ class DataLoader {
|
||||
return names[agentName] || agentName;
|
||||
}
|
||||
|
||||
// Get icon for agent (emoji/symbol representation)
|
||||
// Get icon for agent (SVG file path)
|
||||
getAgentIcon(agentName) {
|
||||
const icons = {
|
||||
'gemini-2.5-flash': '🤖',
|
||||
'qwen3-max': '🧠',
|
||||
'gpt-5': '🔮',
|
||||
'claude-3.7-sonnet': '🎭',
|
||||
'deepseek-chat-v3.1': '🔬',
|
||||
'QQQ': '📈'
|
||||
'gemini-2.5-flash': './figs/google.svg',
|
||||
'qwen3-max': './figs/qwen.svg',
|
||||
'gpt-5': './figs/openai.svg',
|
||||
'claude-3.7-sonnet': './figs/claude-color.svg',
|
||||
'deepseek-chat-v3.1': './figs/deepseek.svg',
|
||||
'QQQ': './figs/stock.svg' // 使用默认图标
|
||||
};
|
||||
return icons[agentName] || '🤖';
|
||||
return icons[agentName] || './figs/stock.svg';
|
||||
}
|
||||
|
||||
// Get agent name without version suffix for icon lookup
|
||||
getAgentIconKey(agentName) {
|
||||
// 处理可能的版本号变体
|
||||
if (agentName.includes('gemini')) return 'gemini-2.5-flash';
|
||||
if (agentName.includes('qwen')) return 'qwen3-max';
|
||||
if (agentName.includes('gpt')) return 'gpt-5';
|
||||
if (agentName.includes('claude')) return 'claude-3.7-sonnet';
|
||||
if (agentName.includes('deepseek')) return 'deepseek-chat-v3.1';
|
||||
return agentName;
|
||||
}
|
||||
|
||||
// Get brand color for agent
|
||||
|
||||
@@ -45,8 +45,8 @@ function populateAgentSelector() {
|
||||
Object.keys(allAgentsData).forEach(agentName => {
|
||||
const option = document.createElement('option');
|
||||
option.value = agentName;
|
||||
const icon = dataLoader.getAgentIcon(agentName);
|
||||
option.textContent = `${icon} ${dataLoader.getAgentDisplayName(agentName)}`;
|
||||
// Use text only for dropdown options (HTML select doesn't support images well)
|
||||
option.textContent = dataLoader.getAgentDisplayName(agentName);
|
||||
select.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user