feat: 添加多维度评分统计面板
This commit is contained in:
@@ -22,6 +22,51 @@
|
|||||||
gap: 20px;
|
gap: 20px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
.rating-stats {
|
||||||
|
background: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.rating-stats h3 {
|
||||||
|
color: #333;
|
||||||
|
font-size: 1.1em;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.rating-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
.rating-item {
|
||||||
|
background: linear-gradient(135deg, #fafaff, #f0f0ff);
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #667eea;
|
||||||
|
}
|
||||||
|
.rating-item .label {
|
||||||
|
font-size: 0.85em;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.rating-item .value {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
.rating-item .value.quality { color: #10b981; }
|
||||||
|
.rating-item .value.efficiency { color: #3b82f6; }
|
||||||
|
.rating-item .value.creativity { color: #8b5cf6; }
|
||||||
|
.rating-item .value.learning { color: #f59e0b; }
|
||||||
|
.rating-item .count {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
.stat-card {
|
.stat-card {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
@@ -276,6 +321,7 @@
|
|||||||
allEntries: [],
|
allEntries: [],
|
||||||
allExperiences: [],
|
allExperiences: [],
|
||||||
taskStats: {},
|
taskStats: {},
|
||||||
|
ratingStats: {},
|
||||||
showCommentForm: null,
|
showCommentForm: null,
|
||||||
commentContent: '',
|
commentContent: '',
|
||||||
scores: { quality: '', efficiency: '', creativity: '', learning: '' }
|
scores: { quality: '', efficiency: '', creativity: '', learning: '' }
|
||||||
@@ -318,6 +364,9 @@
|
|||||||
exp.comments = await loadComments('experience', exp.id);
|
exp.comments = await loadComments('experience', exp.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算评分统计
|
||||||
|
calculateRatingStats();
|
||||||
|
|
||||||
render();
|
render();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
document.getElementById('app').innerHTML = `<div class="error">加载失败:${error.message}</div>`;
|
document.getElementById('app').innerHTML = `<div class="error">加载失败:${error.message}</div>`;
|
||||||
@@ -563,10 +612,73 @@
|
|||||||
<div class="stat-card"><h3>${state.taskStats.completion_rate || 0}%</h3><p>完成率</p></div>
|
<div class="stat-card"><h3>${state.taskStats.completion_rate || 0}%</h3><p>完成率</p></div>
|
||||||
<div class="stat-card"><h3>${state.expStats.total_experiences || 0}</h3><p>经验</p></div>
|
<div class="stat-card"><h3>${state.expStats.total_experiences || 0}</h3><p>经验</p></div>
|
||||||
</div>
|
</div>
|
||||||
|
${renderRatingStats()}
|
||||||
${content}
|
${content}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateRatingStats() {
|
||||||
|
const allComments = [
|
||||||
|
...state.allEntries.flatMap(e => e.comments || []),
|
||||||
|
...state.allTasks.flatMap(t => t.comments || []),
|
||||||
|
...state.allExperiences.flatMap(e => e.comments || [])
|
||||||
|
];
|
||||||
|
|
||||||
|
const stats = {
|
||||||
|
quality: { sum: 0, count: 0 },
|
||||||
|
efficiency: { sum: 0, count: 0 },
|
||||||
|
creativity: { sum: 0, count: 0 },
|
||||||
|
learning: { sum: 0, count: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
allComments.forEach(c => {
|
||||||
|
if (c.quality) { stats.quality.sum += c.quality; stats.quality.count++; }
|
||||||
|
if (c.efficiency) { stats.efficiency.sum += c.efficiency; stats.efficiency.count++; }
|
||||||
|
if (c.creativity) { stats.creativity.sum += c.creativity; stats.creativity.count++; }
|
||||||
|
if (c.learning) { stats.learning.sum += c.learning; stats.learning.count++; }
|
||||||
|
});
|
||||||
|
|
||||||
|
state.ratingStats = {
|
||||||
|
quality: stats.quality.count > 0 ? (stats.quality.sum / stats.quality.count).toFixed(1) : '-',
|
||||||
|
efficiency: stats.efficiency.count > 0 ? (stats.efficiency.sum / stats.efficiency.count).toFixed(1) : '-',
|
||||||
|
creativity: stats.creativity.count > 0 ? (stats.creativity.sum / stats.creativity.count).toFixed(1) : '-',
|
||||||
|
learning: stats.learning.count > 0 ? (stats.learning.sum / stats.learning.count).toFixed(1) : '-',
|
||||||
|
totalComments: allComments.length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderRatingStats() {
|
||||||
|
if (state.ratingStats.totalComments === 0) return '';
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="rating-stats">
|
||||||
|
<h3>📊 多维度评分统计</h3>
|
||||||
|
<div class="rating-grid">
|
||||||
|
<div class="rating-item">
|
||||||
|
<div class="label">📐 完成质量</div>
|
||||||
|
<div class="value quality">${state.ratingStats.quality}</div>
|
||||||
|
<div class="count">${state.ratingStats.totalComments} 条评价</div>
|
||||||
|
</div>
|
||||||
|
<div class="rating-item">
|
||||||
|
<div class="label">⚡ 效率</div>
|
||||||
|
<div class="value efficiency">${state.ratingStats.efficiency}</div>
|
||||||
|
<div class="count">${state.ratingStats.totalComments} 条评价</div>
|
||||||
|
</div>
|
||||||
|
<div class="rating-item">
|
||||||
|
<div class="label">💡 创新性</div>
|
||||||
|
<div class="value creativity">${state.ratingStats.creativity}</div>
|
||||||
|
<div class="count">${state.ratingStats.totalComments} 条评价</div>
|
||||||
|
</div>
|
||||||
|
<div class="rating-item">
|
||||||
|
<div class="label">📚 学习价值</div>
|
||||||
|
<div class="value learning">${state.ratingStats.learning}</div>
|
||||||
|
<div class="count">${state.ratingStats.totalComments} 条评价</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
function switchTab(tab) { state.currentTab = tab; state.selectedTask = null; render(); }
|
function switchTab(tab) { state.currentTab = tab; state.selectedTask = null; render(); }
|
||||||
function selectTask(taskId) { state.selectedTask = state.allTasks.find(t => t.id === taskId); render(); }
|
function selectTask(taskId) { state.selectedTask = state.allTasks.find(t => t.id === taskId); render(); }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user