// ── Export ──────────────────────────────────────────────────────── function buildExportData() { const source=selectedRows.size>0?[...selectedRows].map(idx=>allData[idx]).filter(Boolean):allData; return source.map(({task})=>{ const id=String(task.id), n=notesCache[id]; const markFields={}; MARKS_CONFIG.forEach(m=>{ markFields[m.key]=isMark(id,m.key); markFields[`${m.key}_by`]=getMarkBy(id,m.key)||''; }); return { tasknumber:task.tasknumber||task.id, name:task.name||'', note:n?.text||'', note_by:n?.by||'', note_updated:n?.at?fmtDate(new Date(n.at)):'', ...markFields, comments_count:getCommentCount(id), }; }); } function getExportConfig() { const groups = (exportFieldGroups instanceof Set && exportFieldGroups.size) ? exportFieldGroups : new Set(['note','status','comments']); const mode = exportStatusMode === 'B' ? 'B' : 'A'; return { groups, mode }; } function pickStatus(r) { const m=MARKS_CONFIG.find(m=>r[m.key]); return m?{label:m.exportLabel,by:r[`${m.key}_by`]}:{label:'Без статуса',by:''}; } function dl(content, filename, mime){ const a=document.createElement('a'); a.href=URL.createObjectURL(new Blob([content],{type:mime})); a.download=filename; a.click(); } function exportCSV(){ const d=buildExportData(); const { groups, mode } = getExportConfig(); const h=['Номер','Название']; if (groups.has('note')) { h.push('Заметка','Заметка — кто','Заметка — когда'); } if (groups.has('status')) { if (mode==='A') { MARKS_CONFIG.forEach(m=>h.push(m.exportLabel,`${m.exportLabel} — кто`)); } else { h.push('Статус','Статус — кто'); } } if (groups.has('comments')) { h.push('Комментариев'); } const rows=d.map(r=>{ const row=[ r.tasknumber, r.id, `"${r.name.replace(/"/g,'""')}"` ]; if (groups.has('note')) { row.push( `"${r.note.replace(/"/g,'""')}"`, r.note_by, r.note_updated ); } if (groups.has('status')) { if (mode==='A') { MARKS_CONFIG.forEach(m=>row.push(r[m.key]?'Да':'Нет', r[`${m.key}_by`])); } else { const s = pickStatus(r); row.push(s.label, s.by); } } if (groups.has('comments')) { row.push(String(r.comments_count)); } return row.join(';'); }); dl('\uFEFF'+[h.join(';'),...rows].join('\n'),`intradesk_${datestamp()}.csv`,'text/csv;charset=utf-8'); } function exportJSON(){ dl(JSON.stringify(buildExportData(),null,2),`intradesk_${datestamp()}.json`,'application/json'); } function exportTXT(){ const { groups, mode } = getExportConfig(); const lines=buildExportData().map(r=>{ const parts=[`#${r.tasknumber} — ${r.name}`]; if (groups.has('status')) { if (mode==='A') { const flags=MARKS_CONFIG .filter(m=>r[m.key]) .map(m=>`${m.exportLabel.toUpperCase()} (${r[`${m.key}_by`]})`) .join(', '); if (flags) parts.push(` Статус: ${flags}`); } else { const s = pickStatus(r); parts.push(` Статус: ${s.label}${s.by?` (${s.by})`:''}`); } } if (groups.has('note') && r.note) { parts.push(` Заметка (${r.note_by}): ${r.note}`); } if (groups.has('comments') && r.comments_count) { parts.push(` Наших комментариев: ${r.comments_count}`); } return parts.join('\n'); }); dl(lines.join('\n\n'),`intradesk_${datestamp()}.txt`,'text/plain;charset=utf-8'); }