<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>10x团队效能评估工具</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 1000px;
margin: 0 auto;
padding: 20px;
color: #333;
line-height: 1.6;
}
h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
}
.intro {
background-color: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.assessment-section {
margin-bottom: 30px;
border: 1px solid #ddd;
border-radius: 5px;
padding: 15px;
}
.dimension-title {
font-weight: bold;
font-size: 1.2em;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.dimension-title:hover {
color: #3498db;
}
.dimension-content {
display: none;
margin-left: 20px;
}
.show {
display: block;
}
.rating {
display: flex;
justify-content: space-between;
margin: 20px 0;
flex-wrap: wrap;
}
.rating label {
text-align: center;
width: 19%;
margin-bottom: 10px;
}
.rating input[type="radio"] {
margin: 0 auto 5px;
display: block;
}
.checklist {
margin-bottom: 15px;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
margin: 10px 0;
}
button:hover {
background-color: #2980b9;
}
.results {
margin-top: 30px;
display: none;
}
.chart-container {
display: flex;
justify-content: space-between;
margin-top: 20px;
flex-wrap: wrap;
}
.radar-chart {
width: 400px;
height: 400px;
margin: 0 auto;
}
.results-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.results-table th, .results-table td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
.results-table th {
background-color: #f2f2f2;
}
.improvement-plan {
background-color: #f8f9fa;
padding: 15px;
border-radius: 5px;
margin-top: 20px;
}
.action-buttons {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
@media print {
button {
display: none;
}
}
@media (max-width: 600px) {
.rating label {
width: 18%;
font-size: 0.8em;
}
.radar-chart {
width: 100%;
height: 300px;
}
}
</style>
</head>
<body>
<h1>10x团队效能评估工具</h1>
<div class="intro">
<p>这是一个基于Charity Majors观点开发的团队效能评估工具。通过评估8个关键维度,帮助您识别团队的优势和需要改进的领域。完成评估后,您将获得一份定制化的改进计划。</p>
<p>点击各维度标题可展开更详细的检查项,辅助您更准确地评分。</p>
</div>
<div id="assessment">
<!-- 1. 开发周期 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('deploy-cycle')">
1️⃣ 开发周期
<span>+</span>
</div>
<div id="deploy-cycle" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 我们的部署周期是否少于1天?</p>
<p>- 我们是否能够实现单一提交的独立部署?</p>
<p>- 部署过程是否高度自动化,无需手动干预?</p>
<p>- 团队成员是否清楚了解从代码提交到生产部署的全流程?</p>
<p>- 我们是否定期测量并优化部署时间?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="deploy-cycle" value="1">
严重不足<br>
<small>部署周期超过一周,流程复杂</small>
</label>
<label>
<input type="radio" name="deploy-cycle" value="2">
需要改进<br>
<small>部署周期2-7天,多次手动步骤</small>
</label>
<label>
<input type="radio" name="deploy-cycle" value="3">
达标<br>
<small>部署周期约1天,流程较清晰</small>
</label>
<label>
<input type="radio" name="deploy-cycle" value="4">
良好<br>
<small>可日常多次部署,过程自动化</small>
</label>
<label>
<input type="radio" name="deploy-cycle" value="5">
卓越<br>
<small>持续部署,全自动化</small>
</label>
</div>
</div>
<!-- 2. 错误恢复能力 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('error-recovery')">
2️⃣ 错误恢复能力
<span>+</span>
</div>
<div id="error-recovery" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 任何开发人员都能在10分钟内回滚有问题的代码吗?</p>
<p>- 我们是否有自动化的健康检查来验证部署?</p>
<p>- 回滚过程是否无需管理层审批?</p>
<p>- 团队是否对回滚没有心理负担?</p>
<p>- 我们是否会定期演练故障恢复流程?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="error-recovery" value="1">
严重不足<br>
<small>回滚困难,需多人协作和审批</small>
</label>
<label>
<input type="radio" name="error-recovery" value="2">
需要改进<br>
<small>回滚可行但耗时,流程复杂</small>
</label>
<label>
<input type="radio" name="error-recovery" value="3">
达标<br>
<small>回滚流程标准化,1小时内可完成</small>
</label>
<label>
<input type="radio" name="error-recovery" value="4">
良好<br>
<small>回滚简单迅速,15分钟内可完成</small>
</label>
<label>
<input type="radio" name="error-recovery" value="5">
卓越<br>
<small>自动化回滚或自愈系统</small>
</label>
</div>
</div>
<!-- 3. 开发流程设计 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('dev-process')">
3️⃣ 开发流程设计
<span>+</span>
</div>
<div id="dev-process" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 标准路径是否比特殊路径更简单?</p>
<p>- 危险操作是否有确认步骤或防护措施?</p>
<p>- 我们的工具是否防止常见错误的发生?</p>
<p>- 团队是否有清晰的指导文档和最佳实践?</p>
<p>- 我们是否定期回顾并改进开发流程?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="dev-process" value="1">
严重不足<br>
<small>流程随意,缺乏护栏,常出错</small>
</label>
<label>
<input type="radio" name="dev-process" value="2">
需要改进<br>
<small>有基本流程但不完善,护栏不足</small>
</label>
<label>
<input type="radio" name="dev-process" value="3">
达标<br>
<small>标准流程清晰,有基本护栏</small>
</label>
<label>
<input type="radio" name="dev-process" value="4">
良好<br>
<small>流程优化良好,危险操作有保护</small>
</label>
<label>
<input type="radio" name="dev-process" value="5">
卓越<br>
<small>流程极其顺畅,有智能辅助预防错误</small>
</label>
</div>
</div>
<!-- 4. 监控与可观测性 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('monitoring')">
4️⃣ 监控与可观测性
<span>+</span>
</div>
<div id="monitoring" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 我们能否实时看到用户如何使用产品?</p>
<p>- 新部署代码的性能是否自动监控?</p>
<p>- 异常状况是否有自动告警?</p>
<p>- 开发人员能否轻松查询和分析生产问题?</p>
<p>- 我们是否收集足够的数据来理解系统行为?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="monitoring" value="1">
严重不足<br>
<small>几乎没有监控,问题后知后觉</small>
</label>
<label>
<input type="radio" name="monitoring" value="2">
需要改进<br>
<small>基本监控但覆盖不全,反应滞后</small>
</label>
<label>
<input type="radio" name="monitoring" value="3">
达标<br>
<small>关键指标有监控,能发现大部分问题</small>
</label>
<label>
<input type="radio" name="monitoring" value="4">
良好<br>
<small>全面监控,问题能快速定位</small>
</label>
<label>
<input type="radio" name="monitoring" value="5">
卓越<br>
<small>先进的可观测性工具,预测性分析</small>
</label>
</div>
</div>
<!-- 5. 内部工具建设 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('internal-tools')">
5️⃣ 内部工具建设
<span>+</span>
</div>
<div id="internal-tools" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 我们是否有专门负责工具开发的团队或角色?</p>
<p>- 内部工具预算是否占总工程预算的至少10%?</p>
<p>- 开发者是否定期提供关于工具的反馈?</p>
<p>- 重复性工作是否持续被自动化?</p>
<p>- 我们是否定期评估工具的使用情况和效果?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="internal-tools" value="1">
严重不足<br>
<small>缺乏内部工具,全靠手动操作</small>
</label>
<label>
<input type="radio" name="internal-tools" value="2">
需要改进<br>
<small>有少量基础工具,但不完善</small>
</label>
<label>
<input type="radio" name="internal-tools" value="3">
达标<br>
<small>主要流程有工具支持</small>
</label>
<label>
<input type="radio" name="internal-tools" value="4">
良好<br>
<small>完善的工具链,持续优化</small>
</label>
<label>
<input type="radio" name="internal-tools" value="5">
卓越<br>
<small>先进的内部平台,极大提升效率</small>
</label>
</div>
</div>
<!-- 6. 团队文化 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('team-culture')">
6️⃣ 团队文化
<span>+</span>
</div>
<div id="team-culture" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 团队成员是否愿意承认错误和寻求帮助?</p>
<p>- 不同意见是否被鼓励并认真对待?</p>
<p>- 新想法是否能得到公平评估?</p>
<p>- 我们是否庆祝成功并从失败中学习?</p>
<p>- 团队成员是否感到被赋能而非被微管理?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="team-culture" value="1">
严重不足<br>
<small>充满指责,高压环境</small>
</label>
<label>
<input type="radio" name="team-culture" value="2">
需要改进<br>
<small>基本互相尊重,但缺乏心理安全</small>
</label>
<label>
<input type="radio" name="team-culture" value="3">
达标<br>
<small>友好氛围,可以提问和讨论</small>
</label>
<label>
<input type="radio" name="team-culture" value="4">
良好<br>
<small>开放包容,鼓励创新和犯错</small>
</label>
<label>
<input type="radio" name="team-culture" value="5">
卓越<br>
<small>卓越的心理安全和持续学习文化</small>
</label>
</div>
</div>
<!-- 7. 团队多元化 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('team-diversity')">
7️⃣ 团队多元化
<span>+</span>
</div>
<div id="team-diversity" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 团队是否包含不同背景和经验的成员?</p>
<p>- 不同观点是否得到重视?</p>
<p>- 我们是否有针对不同工作风格的适应性流程?</p>
<p>- 团队是否能在成员缺席时保持高效运作?</p>
<p>- 我们是否避免了单点依赖?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="team-diversity" value="1">
严重不足<br>
<small>单一背景,高度依赖个人</small>
</label>
<label>
<input type="radio" name="team-diversity" value="2">
需要改进<br>
<small>有限的多样性,存在单点风险</small>
</label>
<label>
<input type="radio" name="team-diversity" value="3">
达标<br>
<small>基本多元,主要角色有备份</small>
</label>
<label>
<input type="radio" name="team-diversity" value="4">
良好<br>
<small>良好多元,团队韧性强</small>
</label>
<label>
<input type="radio" name="team-diversity" value="5">
卓越<br>
<small>高度多元,适应性和创新性极强</small>
</label>
</div>
</div>
<!-- 8. 团队结构平衡 -->
<div class="assessment-section">
<div class="dimension-title" onclick="toggleSection('team-structure')">
8️⃣ 团队结构平衡
<span>+</span>
</div>
<div id="team-structure" class="dimension-content">
<div class="checklist">
<p><strong>检查项:</strong></p>
<p>- 团队是否包含初级、中级和高级工程师?</p>
<p>- 每个成员是否都有成长和挑战的机会?</p>
<p>- 初级工程师是否有明确的指导?</p>
<p>- 高级工程师是否有足够时间指导他人?</p>
<p>- 团队是否有明确的技能发展路径?</p>
</div>
</div>
<div class="rating">
<label>
<input type="radio" name="team-structure" value="1">
严重不足<br>
<small>经验结构严重不平衡</small>
</label>
<label>
<input type="radio" name="team-structure" value="2">
需要改进<br>
<small>结构不均衡,缺乏某些层级</small>
</label>
<label>
<input type="radio" name="team-structure" value="3">
达标<br>
<small>基本均衡,有不同经验水平</small>
</label>
<label>
<input type="radio" name="team-structure" value="4">
良好<br>
<small>结构良好,有清晰发展路径</small>
</label>
<label>
<input type="radio" name="team-structure" value="5">
卓越<br>
<small>完美结构,每人都在最佳成长区间</small>
</label>
</div>
</div>
<button id="calculate-btn" onclick="calculateResults()">生成评估结果</button>
</div>
<div id="results" class="results">
<h2>团队效能评估结果</h2>
<div class="chart-container">
<canvas id="radar-chart" class="radar-chart"></canvas>
</div>
<table class="results-table">
<thead>
<tr>
<th>维度</th>
<th>当前评分</th>
<th>描述</th>
</tr>
</thead>
<tbody id="results-table-body">
<!-- 结果将通过JavaScript填充 -->
</tbody>
</table>
<div class="improvement-plan">
<h3>改进计划</h3>
<p>总分: <span id="total-score">0</span>/40 (<span id="score-percentage">0</span>%)</p>
<p><strong>团队优势:</strong></p>
<div id="team-strengths"></div>
<p><strong>优先改进领域:</strong></p>
<div id="improvement-areas"></div>
<p><strong>90天行动计划:</strong></p>
<div id="action-plan"></div>
</div>
<div class="action-buttons">
<button onclick="window.print()">打印结果</button>
<button onclick="saveResults()">保存结果</button>
<button onclick="location.reload()">重新评估</button>
</div>
</div>
<script>
// 维度定义
const dimensions = {
'deploy-cycle': {
name: '开发周期',
descriptions: [
'部署周期超过一周,流程复杂',
'部署周期为2-7天,有多次手动步骤',
'部署周期为1天左右,流程较清晰',
'可以进行日常多次部署,过程自动化',
'持续部署,单一提交可立即上线,全自动化'
],
improvements: [
'实施自动化部署流水线,从代码提交到生产部署全流程自动化',
'将大型部署拆分为多个小型、独立的部署',
'实施特性开关,允许将未完成的功能部署到生产环境但不对用户可见',
'建立部署健康检查机制,自动验证部署是否成功',
'实现单一提交部署能力,缩短从代码提交到生产部署的时间'
]
},
'error-recovery': {
name: '错误恢复能力',
descriptions: [
'回滚困难,需要多人协作和审批',
'回滚可行但耗时,有复杂流程',
'回滚流程标准化,在1小时内可完成',
'回滚简单迅速,15分钟内可完成',
'自动化回滚或自愈系统,几分钟内解决问题'
],
improvements: [
'建立一键回滚机制,减少故障恢复的时间和复杂度',
'实施版本控制和部署历史记录,方便追踪和回滚',
'定期进行灾难恢复演练,确保团队熟悉回滚流程',
'建立自动化测试套件,在部署前捕获潜在问题',
'实施渐进式发布策略,如蓝绿部署或金丝雀发布'
]
},
'dev-process': {
name: '开发流程设计',
descriptions: [
'流程随意,缺乏护栏,常出错',
'有基本流程但不完善,护栏不足',
'标准流程清晰,有基本护栏',
'流程优化良好,危险操作有保护',
'流程极其顺畅,有智能辅助预防错误'
],
improvements: [
'建立并记录标准开发流程,确保团队统一理解',
'实施代码审查流程,捕获潜在问题',
'使用静态代码分析工具,自动检测常见错误',
'为危险操作添加确认步骤或额外审核',
'定期回顾并优化开发流程,减少瓶颈和摩擦'
]
},
'monitoring': {
name: '监控与可观测性',
descriptions: [
'几乎没有监控,问题后知后觉',
'基本监控但覆盖不全,反应滞后',
'关键指标有监控,能发现大部分问题',
'全面监控,问题能快速定位',
'先进的可观测性工具,预测性分析'
],
improvements: [
'实施基本的应用和系统监控,覆盖关键指标',
'建立集中式日志管理系统,方便查询和分析',
'添加业务层面的监控,了解用户行为和体验',
'实施分布式追踪,理解服务间调用关系',
'建立基于异常检测的智能告警系统,减少误报'
]
},
'internal-tools': {
name: '内部工具建设',
descriptions: [
'缺乏内部工具,全靠手动操作',
'有少量基础工具,但不完善',
'主要流程有工具支持',
'完善的工具链,持续优化',
'先进的内部平台,极大提升效率'
],
improvements: [
'指定专门人员或团队负责内部工具开发',
'识别并自动化最常见的手动流程',
'建立内部工具反馈机制,收集改进建议',
'分配固定比例的工程资源用于工具改进',
'建设自助服务平台,减少运维团队的手动干预'
]
},
'team-culture': {
name: '团队文化',
descriptions: [
'充满指责,高压环境',
'基本互相尊重,但缺乏心理安全',
'友好氛围,可以提问和讨论',
'开放包容,鼓励创新和犯错',
'卓越的心理安全和持续学习文化'
],
improvements: [
'实施无指责的事后分析流程,关注系统改进而非个人责任',
'鼓励团队成员分享失败和学习经验',
'建立定期的团队反馈和改进机制',
'培养分享和学习的文化,如技术分享会',
'认可并庆祝团队成员的贡献和成就'
]
},
'team-diversity': {
name: '团队多元化',
descriptions: [
'单一背景,高度依赖个人',
'有限的多样性,存在单点风险',
'基本多元,主要角色有备份',
'良好多元,团队韧性强',
'高度多元,适应性和创新性极强'
],
improvements: [
'识别并消除团队中的单点依赖',
'鼓励知识共享,建立技术文档库',
'实施轮岗或结对编程,扩散知识',
'招募具有不同背景和经验的团队成员',
'创建技能矩阵,确保关键能力有多人掌握'
]
},
'team-structure': {
name: '团队结构平衡',
descriptions: [
'经验结构严重不平衡',
'结构不均衡,缺乏某些层级',
'基本均衡,有不同经验水平',
'结构良好,有清晰发展路径',
'完美结构,每人都在最佳成长区间'
],
improvements: [
'建立明确的职业发展路径,帮助团队成员成长',
'平衡团队的初级、中级和高级工程师比例',
'为初级工程师提供结构化的指导和学习机会',
'确保高级工程师有时间指导他人而不仅是编码',
'为每位团队成员创建个人成长计划'
]
}
};
// 切换部分的显示/隐藏
function toggleSection(id) {
const content = document.getElementById(id);
const titleSpan = content.previousElementSibling.querySelector('span');
if (content.classList.contains('show')) {
content.classList.remove('show');
titleSpan.textContent = '+';
} else {
content.classList.add('show');
titleSpan.textContent = '-';
}
}
// 计算并显示结果
function calculateResults() {
const scores = {};
let totalScore = 0;
let allSelected = true;
// 检查所有维度是否都已评分
for (const dimensionId in dimensions) {
const radioButtons = document.getElementsByName(dimensionId);
let selected = false;
for (const radio of radioButtons) {
if (radio.checked) {
scores[dimensionId] = parseInt(radio.value);
totalScore += scores[dimensionId];
selected = true;
break;
}
}
if (!selected) {
allSelected = false;
break;
}
}
if (!allSelected) {
alert('请为所有维度评分后再生成结果。');
return;
}
// 隐藏评估表单,显示结果
document.getElementById('assessment').style.display = 'none';
document.getElementById('results').style.display = 'block';
// 填充结果表格
const tableBody = document.getElementById('results-table-body');
tableBody.innerHTML = '';
for (const dimensionId in dimensions) {
const dimension = dimensions[dimensionId];
const score = scores[dimensionId];
const row = document.createElement('tr');
const nameCell = document.createElement('td');
nameCell.textContent = dimension.name;
const scoreCell = document.createElement('td');
scoreCell.textContent = score + '/5';
const descCell = document.createElement('td');
descCell.textContent = dimension.descriptions[score - 1];
row.appendChild(nameCell);
row.appendChild(scoreCell);
row.appendChild(descCell);
tableBody.appendChild(row);
}
// 显示总分
document.getElementById('total-score').textContent = totalScore;
document.getElementById('score-percentage').textContent = Math.round((totalScore / 40) * 100);
// 找出优势和改进领域
const strengthsDiv = document.getElementById('team-strengths');
const improvementDiv = document.getElementById('improvement-areas');
strengthsDiv.innerHTML = '';
improvementDiv.innerHTML = '';
// 按分数排序维度
const sortedDimensions = Object.entries(scores)
.sort((a, b) => b[1] - a[1])
.map(entry => entry[0]);
// 显示前3个优势
for (let i = 0; i < Math.min(3, sortedDimensions.length); i++) {
const dimensionId = sortedDimensions[i];
const dimension = dimensions[dimensionId];
const score = scores[dimensionId];
if (score >= 4) {
const p = document.createElement('p');
p.textContent = `${dimension.name} (${score}/5): ${dimension.descriptions[score - 1]}`;
strengthsDiv.appendChild(p);
}
}
if (strengthsDiv.children.length === 0) {
const p = document.createElement('p');
p.textContent = '团队目前没有特别突出的优势领域。';
strengthsDiv.appendChild(p);
}
// 显示需要改进的领域(分数低于3的)
const improvementAreas = [];
for (let i = sortedDimensions.length - 1; i >= 0; i--) {
const dimensionId = sortedDimensions[i];
const dimension = dimensions[dimensionId];
const score = scores[dimensionId];
if (score <= 3) {
improvementAreas.push({
id: dimensionId,
name: dimension.name,
score: score
});
const p = document.createElement('p');
p.textContent = `${dimension.name} (${score}/5): ${dimension.descriptions[score - 1]}`;
improvementDiv.appendChild(p);
}
if (improvementAreas.length >= 3) break;
}
if (improvementDiv.children.length === 0) {
const p = document.createElement('p');
p.textContent = '团队在所有领域表现良好,可以专注于进一步提升优势领域。';
improvementDiv.appendChild(p);
}
// 生成行动计划
const actionPlanDiv = document.getElementById('action-plan');
actionPlanDiv.innerHTML = '';
if (improvementAreas.length > 0) {
for (let i = 0; i < Math.min(3, improvementAreas.length); i++) {
const area = improvementAreas[i];
const dimension = dimensions[area.id];
const p = document.createElement('p');
p.innerHTML = `<strong>${i + 1}. ${dimension.name}:</strong> ${dimension.improvements[Math.min(4, 5 - area.score)]}`;
actionPlanDiv.appendChild(p);
}
} else {
// 如果没有明显的改进领域,建议提升最强的领域
const topDimensionId = sortedDimensions[0];
const topDimension = dimensions[topDimensionId];
const p = document.createElement('p');
p.innerHTML = `<strong>继续增强团队最强领域 (${topDimension.name}):</strong> ${topDimension.improvements[0]}`;
actionPlanDiv.appendChild(p);
}
// 绘制雷达图
drawRadarChart(scores);
}
// 绘制雷达图
function drawRadarChart(scores) {
const canvas = document.getElementById('radar-chart');
const ctx = canvas.getContext('2d');
// 设置canvas大小
canvas.width = 400;
canvas.height = 400;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = Math.min(centerX, centerY) - 30;
// 绘制背景
ctx.fillStyle = '#f8f9fa';
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
ctx.fill();
// 绘制刻度线
for (let i = 1; i <= 5; i++) {
const currentRadius = (radius / 5) * i;
ctx.strokeStyle = '#ddd';
ctx.beginPath();
ctx.arc(centerX, centerY, currentRadius, 0, Math.PI * 2);
ctx.stroke();
}
// 绘制轴线
const dimensionCount = Object.keys(dimensions).length;
const angleIncrement = (Math.PI * 2) / dimensionCount;
for (let i = 0; i < dimensionCount; i++) {
const angle = i * angleIncrement;
ctx.strokeStyle = '#999';
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.lineTo(
centerX + radius * Math.cos(angle),
centerY + radius * Math.sin(angle)
);
ctx.stroke();
// 绘制维度标签
const labelX = centerX + (radius + 15) * Math.cos(angle);
const labelY = centerY + (radius + 15) * Math.sin(angle);
ctx.fillStyle = '#333';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const dimensionId = Object.keys(dimensions)[i];
ctx.fillText(dimensions[dimensionId].name, labelX, labelY);
}
// 绘制数据点
const dataPoints = [];
for (let i = 0; i < dimensionCount; i++) {
const dimensionId = Object.keys(dimensions)[i];
const score = scores[dimensionId];
const angle = i * angleIncrement;
const pointRadius = (radius / 5) * score;
const pointX = centerX + pointRadius * Math.cos(angle);
const pointY = centerY + pointRadius * Math.sin(angle);
dataPoints.push({ x: pointX, y: pointY });
}
// 绘制数据区域
ctx.beginPath();
ctx.moveTo(dataPoints[0].x, dataPoints[0].y);
for (let i = 1; i < dataPoints.length; i++) {
ctx.lineTo(dataPoints[i].x, dataPoints[i].y);
}
ctx.lineTo(dataPoints[0].x, dataPoints[0].y);
ctx.fillStyle = 'rgba(52, 152, 219, 0.3)';
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(52, 152, 219, 0.8)';
ctx.stroke();
// 绘制数据点
for (const point of dataPoints) {
ctx.beginPath();
ctx.arc(point.x, point.y, 5, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(52, 152, 219, 1)';
ctx.fill();
ctx.stroke();
}
}
// 保存结果为JSON文件
function saveResults() {
const scores = {};
for (const dimensionId in dimensions) {
const radioButtons = document.getElementsByName(dimensionId);
for (const radio of radioButtons) {
if (radio.checked) {
scores[dimensionId] = parseInt(radio.value);
break;
}
}
}
const resultsData = {
scores: scores,
timestamp: new Date().toISOString(),
totalScore: Object.values(scores).reduce((sum, score) => sum + score, 0)
};
const dataStr = JSON.stringify(resultsData, null, 2);
const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr);
const exportFileDefaultName = '团队效能评估_' + new Date().toISOString().split('T')[0] + '.json';
const linkElement = document.createElement('a');
linkElement.setAttribute('href', dataUri);
linkElement.setAttribute('download', exportFileDefaultName);
linkElement.click();
}
</script>
</body>
</html>
index.html
style.css
index.js
index.html