const state = { data: null }; const statusLabels = { normal: "正常", risk: "有风险", need_help: "需要支持" }; function text(value) { return String(value || ""); } function escapeHtml(value) { return text(value).replace(/[&<>"']/g, (char) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[char])); } function render() { const employeeQuery = document.querySelector("#employee-filter").value.trim().toLowerCase(); const keywordQuery = document.querySelector("#keyword-filter").value.trim().toLowerCase(); const onlyBlockers = document.querySelector("#blocker-filter").checked; const data = state.data; document.querySelector("#stats").innerHTML = ` 应提交:${data.expectedCount} 已提交:${data.submittedCount} 未提交:${data.missingCount} `; const reports = data.reports.filter((report) => { const employeeMatch = report.employee_name.toLowerCase().includes(employeeQuery); const searchable = [ report.today_done, report.tomorrow_plan, report.blockers, report.help_needed, statusLabels[report.report_status] ].join(" ").toLowerCase(); const keywordMatch = searchable.includes(keywordQuery); const blockerMatch = !onlyBlockers || report.blockers || report.help_needed || report.report_status === "need_help"; return employeeMatch && keywordMatch && blockerMatch; }); document.querySelector("#reports").innerHTML = reports.length ? reports.map((report) => `

${escapeHtml(report.employee_name)}

${statusLabels[report.report_status] || "正常"}
今日完成
${escapeHtml(report.today_done)}
明日计划
${escapeHtml(report.tomorrow_plan)}
遇到的问题
${escapeHtml(report.blockers || "无")}
需要协助
${escapeHtml(report.help_needed || "无")}

提交时间:${escapeHtml(report.updated_at)}

`).join("") : "

当前筛选下没有日报。

"; document.querySelector("#missing").textContent = data.missing.length ? data.missing.map((employee) => employee.name).join("、") : "无"; } async function loadReports() { const date = document.querySelector("#date-filter").value; document.querySelector("#export-link").href = `/api/reports/export?date=${date}`; const response = await fetch(`/api/reports?date=${date}`); state.data = await response.json(); render(); } document.querySelector("#date-filter").addEventListener("change", loadReports); document.querySelector("#employee-filter").addEventListener("input", render); document.querySelector("#keyword-filter").addEventListener("input", render); document.querySelector("#blocker-filter").addEventListener("change", render); document.querySelector("#copy-summary").addEventListener("click", async () => { const data = state.data; const lines = [ `${data.date} 日报汇总`, `已提交:${data.submittedCount}/${data.expectedCount}`, `未提交:${data.missing.length ? data.missing.map((employee) => employee.name).join("、") : "无"}` ]; await navigator.clipboard.writeText(lines.join("\n")); }); loadReports();