сбор оценок напрямую в Google Таблицу через Apps Script
This commit is contained in:
parent
108542c504
commit
5de6ebe80b
54
index.html
54
index.html
@ -339,9 +339,9 @@ footer a{color:var(--cyan);text-decoration:none;font-weight:600}
|
|||||||
<button class="btn" id="cSubmit" type="button">Отправить результат</button>
|
<button class="btn" id="cSubmit" type="button">Отправить результат</button>
|
||||||
<span class="cmsg" id="cMsg"></span>
|
<span class="cmsg" id="cMsg"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="collect-priv">Данные уходят через сервис FormSubmit. Первая отправка активируется по ссылке в письме владельцу сайта. Анализировать потом удобно в Google Таблицах: FormSubmit → экспорт в CSV.</div>
|
<div class="collect-priv">Данные сохраняются напрямую в Google Таблицу владельца сайта. Анализ — сводными таблицами по возрастам, сферам и статусам. Имена и контакты детей не собираются.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collect-off" id="collectOff"><b>Сбор данных скоро будет подключён.</b> Владельцу сайта нужно указать email для получения результатов — после этого форма станет активной.</div>
|
<div class="collect-off" id="collectOff"><b>Сбор данных скоро будет подключён.</b> Владельцу сайта нужно настроить приёмник (Google Таблицу) — после этого форма станет активной.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -806,8 +806,8 @@ function render(){
|
|||||||
|
|
||||||
render();
|
render();
|
||||||
|
|
||||||
/* ====== Сбор результатов через FormSubmit (без регистрации) ====== */
|
/* ====== Сбор результатов в Google Таблицу (Apps Script веб-приложение) ====== */
|
||||||
const COLLECT_EMAIL = "tsai.e@amu.kz"; // ← email владельца сайта для получения результатов
|
const SHEET_URL = "https://script.google.com/macros/s/AKfycbz0ohb-nons2KY4Y1JUzKB-FNeLpRz5J98v7XM6L5Ic_flUvkbeEyoYcC8jmHeyc220lA/exec";
|
||||||
const collectForm = document.getElementById('collectForm');
|
const collectForm = document.getElementById('collectForm');
|
||||||
const collectOff = document.getElementById('collectOff');
|
const collectOff = document.getElementById('collectOff');
|
||||||
const cEmail = document.getElementById('cEmail');
|
const cEmail = document.getElementById('cEmail');
|
||||||
@ -815,7 +815,7 @@ const cConsent = document.getElementById('cConsent');
|
|||||||
const cSubmit = document.getElementById('cSubmit');
|
const cSubmit = document.getElementById('cSubmit');
|
||||||
const cMsg = document.getElementById('cMsg');
|
const cMsg = document.getElementById('cMsg');
|
||||||
|
|
||||||
if(COLLECT_EMAIL){
|
if(SHEET_URL){
|
||||||
collectForm.style.display = 'grid';
|
collectForm.style.display = 'grid';
|
||||||
collectOff.style.display = 'none';
|
collectOff.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
@ -823,11 +823,12 @@ if(COLLECT_EMAIL){
|
|||||||
collectOff.style.display = 'block';
|
collectOff.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildPayload(){
|
function buildSheetPayload(){
|
||||||
const block = DATA[currentAge];
|
const block = DATA[currentAge];
|
||||||
const res = {'Возраст': currentAge};
|
const gotParts=[], missParts=[];
|
||||||
let total=0, done=0;
|
let total=0, done=0;
|
||||||
Object.keys(SPHERES).forEach(key=>{
|
const out = {age: currentAge};
|
||||||
|
['phys','cogn','lang','socio'].forEach(key=>{
|
||||||
const items = block[key]||[];
|
const items = block[key]||[];
|
||||||
let d=0; const got=[], miss=[];
|
let d=0; const got=[], miss=[];
|
||||||
items.forEach((it,i)=>{
|
items.forEach((it,i)=>{
|
||||||
@ -837,38 +838,39 @@ function buildPayload(){
|
|||||||
total+=items.length; done+=d;
|
total+=items.length; done+=d;
|
||||||
const p = items.length?Math.round(d/items.length*100):0;
|
const p = items.length?Math.round(d/items.length*100):0;
|
||||||
const st = p>=70?'Хорошо':(p>=40?'Осваивается':'Отстаёт');
|
const st = p>=70?'Хорошо':(p>=40?'Осваивается':'Отстаёт');
|
||||||
res['Сфера: '+SPHERES[key].name] = d+' / '+items.length+' ('+st+', '+p+'%)';
|
out[key+'_done']=d; out[key+'_len']=items.length; out[key+'_st']=st;
|
||||||
res[SPHERES[key].name+' — освоено'] = got.join('; ')||'—';
|
if(got.length) gotParts.push(SPHERES[key].name+': '+got.join(', '));
|
||||||
res[SPHERES[key].name+' — не освоено'] = miss.join('; ')||'—';
|
if(miss.length) missParts.push(SPHERES[key].name+': '+miss.join(', '));
|
||||||
});
|
});
|
||||||
const pct = total?Math.round(done/total*100):0;
|
const pct = total?Math.round(done/total*100):0;
|
||||||
const overall = pct>=70?'Развитие идёт хорошо':(pct>=40?'Некоторые навыки осваиваются':'Есть сферы, требующие внимания');
|
out.pct = pct;
|
||||||
res['Общий статус'] = overall+' ('+done+'/'+total+', '+pct+'%)';
|
out.overall = pct>=70?'Развитие идёт хорошо':(pct>=40?'Некоторые навыки осваиваются':'Есть сферы, требующие внимания');
|
||||||
res['Дата отправки'] = new Date().toLocaleString('ru-RU');
|
out.got = gotParts.join(' | ');
|
||||||
if(cEmail.value.trim()){ res['Email родителя (необязательно)'] = cEmail.value.trim(); }
|
out.miss = missParts.join(' | ');
|
||||||
return res;
|
out.email = cEmail.value.trim();
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cSubmit.onclick = async () => {
|
cSubmit.onclick = async () => {
|
||||||
if(!COLLECT_EMAIL){ cMsg.textContent='Сбор данных ещё не подключён.'; cMsg.className='cmsg err'; return; }
|
if(!SHEET_URL){ cMsg.textContent='Приёмник данных не подключён.'; cMsg.className='cmsg err'; return; }
|
||||||
let done=0; Object.keys(checked).forEach(k=>{ if(k.startsWith(currentAge+'|')&&checked[k]) done++; });
|
let done=0; Object.keys(checked).forEach(k=>{ if(k.startsWith(currentAge+'|')&&checked[k]) done++; });
|
||||||
if(done===0){ cMsg.textContent='Сначала отметьте хотя бы один навык выше.'; cMsg.className='cmsg err'; return; }
|
if(done===0){ cMsg.textContent='Сначала отметьте хотя бы один навык выше.'; cMsg.className='cmsg err'; return; }
|
||||||
if(!cConsent.checked){ cMsg.textContent='Подтвердите согласие на обработку данных.'; cMsg.className='cmsg err'; return; }
|
if(!cConsent.checked){ cMsg.textContent='Подтвердите согласие на обработку данных.'; cMsg.className='cmsg err'; return; }
|
||||||
const payload = buildPayload();
|
const payload = buildSheetPayload();
|
||||||
payload._subject = 'Оценка развития ребёнка — '+currentAge;
|
|
||||||
payload._template = 'table';
|
|
||||||
payload._captcha = 'false';
|
|
||||||
cSubmit.disabled = true;
|
cSubmit.disabled = true;
|
||||||
cMsg.textContent='Отправляем…'; cMsg.className='cmsg';
|
cMsg.textContent='Отправляем…'; cMsg.className='cmsg';
|
||||||
try{
|
try{
|
||||||
const r = await fetch('https://formsubmit.co/ajax/'+encodeURIComponent(COLLECT_EMAIL), {
|
await fetch(SHEET_URL, {
|
||||||
method:'POST',
|
method:'POST',
|
||||||
headers:{'Content-Type':'application/json','Accept':'application/json'},
|
mode:'no-cors',
|
||||||
|
headers:{'Content-Type':'text/plain;charset=utf-8'},
|
||||||
body: JSON.stringify(payload)
|
body: JSON.stringify(payload)
|
||||||
});
|
});
|
||||||
if(r.ok){ cMsg.textContent='✓ Спасибо! Результат отправлен.'; cMsg.className='cmsg ok'; cConsent.checked=false; }
|
cMsg.textContent='✓ Готово! Результат сохранён в таблицу.'; cMsg.className='cmsg ok';
|
||||||
else { cMsg.textContent='Не удалось отправить. Попробуйте позже.'; cMsg.className='cmsg err'; }
|
cConsent.checked=false;
|
||||||
}catch(e){ cMsg.textContent='Нет связи с сервером. Проверьте интернет.'; cMsg.className='cmsg err'; }
|
}catch(e){
|
||||||
|
cMsg.textContent='Нет связи. Проверьте интернет и попробуйте снова.'; cMsg.className='cmsg err';
|
||||||
|
}
|
||||||
cSubmit.disabled = false;
|
cSubmit.disabled = false;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user