inline all JS to fix upload
This commit is contained in:
parent
230bc222ea
commit
cb8c871cc1
116
index.html
116
index.html
@ -58,8 +58,120 @@
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||
<script>
|
||||
document.getElementById('uploadBtn').addEventListener('click', function() {
|
||||
document.getElementById('excelFile').click();
|
||||
});
|
||||
document.getElementById('excelFile').addEventListener('change', function(e) {
|
||||
var file = e.target.files[0];
|
||||
if (file) {
|
||||
document.getElementById('statusMsg').textContent = 'Выбран: ' + file.name;
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(ev) {
|
||||
try {
|
||||
var arr = new Uint8Array(ev.target.result);
|
||||
var wb = XLSX.read(arr, {type: 'array'});
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var rows = XLSX.utils.sheet_to_json(ws, {defval: ''});
|
||||
if (rows.length > 0) {
|
||||
document.getElementById('statusMsg').textContent = 'Загружено строк: ' + rows.length;
|
||||
buildDashboard(rows);
|
||||
}
|
||||
} catch(err) {
|
||||
document.getElementById('statusMsg').textContent = 'Ошибка: ' + err.message;
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script>
|
||||
function buildDashboard(raw) {
|
||||
document.getElementById('uploadSection').classList.add('hidden');
|
||||
document.getElementById('dashboard').classList.remove('hidden');
|
||||
|
||||
var norm = {
|
||||
'фио':'name','ф.и.о':'name','сотрудник':'name','employee':'name','имя':'name',
|
||||
'дивизион':'div','подразделение':'div','отдел':'div','division':'div','department':'div',
|
||||
'курс':'course','обучение':'course','training':'course','программа':'course',
|
||||
'тренинг':'course','название тренинга':'course','название курса':'course','название обучения':'course',
|
||||
'тема':'course','тема курса':'course','дисциплина':'course','модуль':'course','module':'course',
|
||||
'статус':'status','status':'status','состояние':'status',
|
||||
'оценка':'score','балл':'score','баллы':'score','рейтинг':'score','ball':'score','score':'score',
|
||||
'тренер':'trainer','преподаватель':'trainer','trainer':'trainer','coach':'trainer',
|
||||
'дата':'date','date':'date'
|
||||
};
|
||||
|
||||
var d = raw.map(function(r) {
|
||||
var out = {};
|
||||
for (var k in r) {
|
||||
var key = k.toLowerCase().replace(/\s+/g,' ').trim();
|
||||
out[norm[key] || key] = r[k];
|
||||
}
|
||||
return out;
|
||||
});
|
||||
|
||||
var allN = {}, scores = [], train = {}, trainers = {};
|
||||
|
||||
d.forEach(function(r) {
|
||||
allN[r.name] = true;
|
||||
var sc = parseFloat(r.score);
|
||||
if (!isNaN(sc) && sc > 0) scores.push(sc);
|
||||
|
||||
var c = r.course || 'Без темы';
|
||||
if (!train[c]) train[c] = {all:{}, ok:{}, sc:[], tr:{}};
|
||||
train[c].all[r.name] = true;
|
||||
var s = (r.status||'').toLowerCase();
|
||||
if (s.indexOf('завершен')>=0 || s.indexOf('пройден')>=0 || s==='completed' || s==='ок') train[c].ok[r.name] = true;
|
||||
if (!isNaN(sc) && sc > 0) train[c].sc.push(sc);
|
||||
if (r.trainer) train[c].tr[r.trainer] = true;
|
||||
|
||||
var tr = r.trainer || '—';
|
||||
if (!trainers[tr]) trainers[tr] = {n:0, sc:[], topics:[], trained:{}, divisions:{}};
|
||||
trainers[tr].n++;
|
||||
if (!isNaN(sc) && sc > 0) trainers[tr].sc.push(sc);
|
||||
if (c && c !== 'Без темы') trainers[tr].topics.push(c);
|
||||
if (r.name) trainers[tr].trained[r.name] = true;
|
||||
var dv = r.division || '—';
|
||||
trainers[tr].divisions[dv] = true;
|
||||
});
|
||||
|
||||
document.getElementById('statTotal').textContent = Object.keys(allN).length;
|
||||
document.getElementById('statAvg').textContent = scores.length ? (scores.reduce(function(a,b){return a+b},0)/scores.length).toFixed(1) : '—';
|
||||
|
||||
document.querySelector('#tblTrainings tbody').innerHTML = Object.keys(train).map(function(k){
|
||||
var t=train[k], tot=Object.keys(t.all).length, ok=Object.keys(t.ok).length;
|
||||
var avg=t.sc.length?(t.sc.reduce(function(a,b){return a+b},0)/t.sc.length).toFixed(1):'—';
|
||||
var trn=Object.keys(t.tr).join(', ')||'—';
|
||||
return '<tr><td><b>'+k+'</b></td><td>'+ok+'</td><td>'+(tot-ok)+'</td><td>'+(tot?Math.round(ok/tot*100):0)+'%</td><td>'+avg+'</td><td>'+trn+'</td></tr>';
|
||||
}).join('');
|
||||
|
||||
document.querySelector('#tblTrainers tbody').innerHTML = Object.keys(trainers).map(function(tr) {
|
||||
var t = trainers[tr];
|
||||
var topics = (t.topics && t.topics.length > 0) ? Array.from(new Set(t.topics)).join(', ') : '—';
|
||||
var avgScore = t.sc && t.sc.length ? (t.sc.reduce(function(a,b){return a+b},0)/t.sc.length).toFixed(1) : '—';
|
||||
var trainedCount = t.trained ? Object.keys(t.trained).length : 0;
|
||||
var divisions = t.divisions ? Array.from(new Set(Object.keys(t.divisions))).join(', ') : '—';
|
||||
return '<tr><td><b>' + tr + '</b></td><td>' + t.n + '</td><td>' + topics + '</td><td>' + trainedCount + '</td><td>' + avgScore + '</td><td>' + divisions + '</td></tr>';
|
||||
}).join('');
|
||||
|
||||
cph = {};
|
||||
d.forEach(function(r){if(!cph[r.name])cph[r.name]={d:r.division||'',c:{} };if(r.course)cph[r.name].c[r.course]=true});
|
||||
var champs=Object.keys(cph).map(function(n){return{name:n,div:cph[n].d,cnt:Object.keys(cph[n].c).length}})
|
||||
.sort(function(a,b){return b.cnt-a.cnt}).slice(0,10);
|
||||
document.querySelector('#tblChamp tbody').innerHTML = champs.map(function(c){
|
||||
return '<tr><td>'+c.name+'</td><td>'+c.div+'</td><td>'+c.cnt+'</td></tr>';
|
||||
}).join('');
|
||||
|
||||
document.querySelector('#tblNoTrain tbody').innerHTML = Object.keys(allN).slice(0,20).map(function(n){
|
||||
return '<tr><td>'+n+'</td><td>'+(cph[n]?cph[n].d:'')+'</td></tr>';
|
||||
}).join('');
|
||||
|
||||
document.querySelector('#tblAll tbody').innerHTML = d.map(function(r){
|
||||
return '<tr><td>'+(r.name||'')+'</td><td>'+(r.division||'')+'</td><td>'+(r.course||'')+'</td><td>'+(r.status||'')+'</td><td>'+(r.score||'')+'</td><td>'+(r.trainer||'')+'</td></tr>';
|
||||
}).join('');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user