Перейти к основному содержимому
clawam tools
Инструменты Документы Daoark EN Главная Главная / Быт и полезное › Главная manifest.json &"']/g, function(c) { return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }); } function parseTasks(text) { var lines = text.split('\n'); var out = []; for (var i = 0; i < lines.length; i++) { var l = lines[i].trim(); if (!l || l[0] === '#') continue; var parts = l.split(',').map(function(p) { return p.trim(); }); if (parts.length < 3) continue; var name = parts[0], date = parts[1], dur = parseInt(parts[2], 10); if (!name || !date || isNaN(dur) || dur < 1) continue; out.push({ name: name, start: date, duration: dur }); } return out; } function dateToObj(s) { var m = s.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/); if (!m) return null; return { y: +m[1], m: +m[2], d: +m[3] }; } function daysBetween(a, b) { var ms = (new Date(b.y, b.m - 1, b.d) - new Date(a.y, a.m - 1, a.d)) / 86400000; return Math.round(ms); } function addDays(d, n) { var x = new Date(d.y, d.m - 1, d.d + n); return { y: x.getFullYear(), m: x.getMonth() + 1, d: x.getDate() }; } function fmtDate(d) { return d.y + '-' + String(d.m).padStart(2, '0') + '-' + String(d.d).padStart(2, '0'); } var COLORS = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#06b6d4']; var lastSvg = ''; function doGen() { try { var tasks = parseTasks(getVal('text-a')); if (tasks.length === 0) { showError('请输入任务列表'); return; } // 解析开始日 for (var i = 0; i < tasks.length; i++) { var d = dateToObj(tasks[i].start); if (!d) { showError('日期格式错: ' + tasks[i].start); return; } tasks[i].startObj = d; } // 项目开始日 var projectStart = $('startdate').value; var projStartObj; if (projectStart) { projStartObj = dateToObj(projectStart); } else { tasks.sort(function(a, b) { return daysBetween(a.startObj, b.startObj) - daysBetween(b.startObj, a.startObj) > 0 ? -1 : 1; }); projStartObj = tasks.reduce(function(min, t) { return daysBetween(t.startObj, min) > 0 ? min : t.startObj; }, tasks[0].startObj); } // 总天数 var endObj = tasks.reduce(function(max, t) { var e = addDays(t.startObj, t.duration - 1); return daysBetween(max, e) > 0 ? max : e; }, projStartObj); var totalDays = daysBetween(projStartObj, endObj) + 1; // 渲染 var leftPad = 200, topPad = 40, rowH = 32, colW = 18; var W = leftPad + totalDays * colW + 20; var H = topPad + tasks.length * rowH + 30; var svg = ''; // 时间轴 for (var d2 = 0; d2 < totalDays; d2++) { var dd = addDays(projStartObj, d2); var x = leftPad + d2 * colW; if ((d2 % 7 === 0) || d2 === totalDays - 1) { svg += ''; svg += '' + fmtDate(dd).substring(5) + ''; } } // 任务 for (var t = 0; t < tasks.length; t++) { var task = tasks[t]; var ty = topPad + t * rowH; // 名字 svg += '' + escapeXml(task.name) + ''; // 条 var tx = leftPad + daysBetween(projStartObj, task.startObj) * colW; var tw = task.duration * colW; var c = COLORS[t % COLORS.length]; svg += ''; svg += '' + task.duration + 'd'; } // 时间轴底线 svg += ''; svg += ''; lastSvg = svg; showResult(svg + '\n(本 SVG 已生成,含 ' + tasks.length + ' 个任务,跨度 ' + totalDays + ' 天)', tasks.length + ' 任务 · ' + totalDays + ' 天'); } catch (e) { showError('生成失败: ' + (e.message || e)); } } $('btn-main').addEventListener('click', function(e) { e.preventDefault(); doGen(); }); $('btn-copy').addEventListener('click', function() { if (lastSvg && navigator.clipboard) navigator.clipboard.writeText(lastSvg); }); $('btn-download').addEventListener('click', function() { if (!lastSvg) return; var blob = new Blob([lastSvg], { type: 'image/svg+xml;charset=utf-8' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'gantt.svg'; a.click(); URL.revokeObjectURL(url); }); $('btn-clear').addEventListener('click', function() { var inputs = document.querySelectorAll('input,textarea'); for (var i = 0; i < inputs.length; i++) inputs[i].value = inputs[i].defaultValue; lastSvg = ''; var ra = $('result-area'); ra.hidden = true; ra.style.display = 'none'; var em = $('error-msg'); em.hidden = true; em.style.display = 'none'; $('btn-copy').style.display = 'none'; $('btn-download').style.display = 'none'; }); })();