191 lines
6.7 KiB
JavaScript
191 lines
6.7 KiB
JavaScript
togglePreview = function (mode) {
|
||
const previewBtn = document.getElementById('preview-toggle');
|
||
const sourceBtn = document.getElementById('source-toggle');
|
||
const reportContent = document.getElementById('report-content');
|
||
const markdownSource = document.getElementById('markdown-source');
|
||
const sourceContent = document.getElementById('source-content');
|
||
|
||
if (mode === 'preview') {
|
||
previewBtn.classList.add('active');
|
||
sourceBtn.classList.remove('active');
|
||
reportContent.style.display = 'block';
|
||
markdownSource.style.display = 'none';
|
||
} else {
|
||
previewBtn.classList.remove('active');
|
||
sourceBtn.classList.add('active');
|
||
reportContent.style.display = 'none';
|
||
markdownSource.style.display = 'block';
|
||
|
||
// 显示原始Markdown源代码
|
||
const markdown = reportContent.getAttribute('data-markdown');
|
||
sourceContent.textContent = markdown;
|
||
}
|
||
};
|
||
|
||
// 设置默认周次为当前周
|
||
function getCurrentWeek() {
|
||
const now = new Date();
|
||
const startOfYear = new Date(now.getFullYear(), 0, 1);
|
||
const days = Math.floor((now - startOfYear) / (24 * 60 * 60 * 1000));
|
||
const weekNumber = Math.ceil((days + 1) / 7);
|
||
return `${now.getFullYear()}-W${weekNumber.toString().padStart(2, '0')}`;
|
||
}
|
||
|
||
// 页面加载时设置默认周次
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
document.getElementById('week').value = getCurrentWeek();
|
||
});
|
||
|
||
function showLoading() {
|
||
document.getElementById('loading').style.display = 'block';
|
||
document.getElementById('report-container').style.display = 'none';
|
||
document.getElementById('error').style.display = 'none';
|
||
}
|
||
|
||
function hideLoading() {
|
||
document.getElementById('loading').style.display = 'none';
|
||
}
|
||
|
||
function showError(message) {
|
||
document.getElementById('error').style.display = 'block';
|
||
document.getElementById('error').textContent = message;
|
||
}
|
||
|
||
function generateCurrentWeekReport() {
|
||
document.getElementById('week').value = getCurrentWeek();
|
||
generateReport();
|
||
}
|
||
|
||
|
||
function generateReport() {
|
||
const week = document.getElementById('week').value;
|
||
if (!week) {
|
||
showError('请选择周次');
|
||
return;
|
||
}
|
||
|
||
// 转换格式:YYYY-WWW 到 YYYY-WW
|
||
const weekFormatted = week.replace('W', '');
|
||
|
||
showLoading();
|
||
|
||
fetch(`api/reports/weekly?week=${weekFormatted}`)
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
hideLoading();
|
||
|
||
if (data.success) {
|
||
// 保存原始Markdown内容到data属性
|
||
document.getElementById('report-content').setAttribute('data-markdown', data.report);
|
||
|
||
// 使用专业的Markdown解析器将Markdown转换为HTML并显示
|
||
const htmlContent = parseMarkdownWithTables(data.report);
|
||
document.getElementById('report-content').innerHTML = htmlContent;
|
||
|
||
// 重置为预览模式
|
||
togglePreview('preview');
|
||
|
||
document.getElementById('report-container').style.display = 'block';
|
||
|
||
// 显示统计数据
|
||
if (data.statistics) {
|
||
displayStatistics(data.statistics);
|
||
document.getElementById('statistics').style.display = 'block';
|
||
|
||
// 显示分类图表
|
||
if (data.statistics.category_breakdown) {
|
||
displayCategoryChart(data.statistics.category_breakdown);
|
||
document.getElementById('category-chart').style.display = 'block';
|
||
}
|
||
}
|
||
} else {
|
||
showError('生成周报失败:' + data.error);
|
||
}
|
||
})
|
||
.catch(error => {
|
||
hideLoading();
|
||
showError('网络错误:' + error.message);
|
||
});
|
||
}
|
||
|
||
function displayStatistics(stats) {
|
||
const statGrid = document.getElementById('stat-grid');
|
||
statGrid.innerHTML = '';
|
||
|
||
const statistics = [
|
||
{label: '本周消息量', value: stats.week_message_count, unit: '条'},
|
||
{label: '上周消息量', value: stats.last_week_message_count, unit: '条'},
|
||
{label: '消息变化率', value: stats.message_change_rate.toFixed(1), unit: '%'},
|
||
{label: '本周活跃用户', value: stats.week_active_users, unit: '人'},
|
||
{label: '群组数量', value: stats.group_count, unit: '个'},
|
||
{label: '成员总数', value: stats.member_count, unit: '人'},
|
||
{label: '问答记录数', value: stats.qa_count, unit: '条'}
|
||
];
|
||
|
||
statistics.forEach(stat => {
|
||
const statItem = document.createElement('div');
|
||
statItem.className = 'stat-item';
|
||
statItem.innerHTML = `
|
||
<div class="stat-value">${stat.value}${stat.unit}</div>
|
||
<div class="stat-label">${stat.label}</div>
|
||
`;
|
||
statGrid.appendChild(statItem);
|
||
});
|
||
}
|
||
|
||
function displayCategoryChart(categories) {
|
||
const categoryItems = document.getElementById('category-items');
|
||
categoryItems.innerHTML = '';
|
||
|
||
Object.entries(categories).forEach(([category, percentage]) => {
|
||
const categoryItem = document.createElement('div');
|
||
categoryItem.className = 'category-item';
|
||
categoryItem.innerHTML = `
|
||
<span style="min-width: 120px;">${category}</span>
|
||
<div class="category-bar" style="width: ${percentage * 2}px;"></div>
|
||
<span style="min-width: 40px; text-align: right;">${percentage}%</span>
|
||
`;
|
||
categoryItems.appendChild(categoryItem);
|
||
});
|
||
}
|
||
|
||
function exportReport() {
|
||
const reportContent = document.getElementById('report-content').getAttribute('data-markdown');
|
||
if (!reportContent) {
|
||
showError('请先生成周报');
|
||
return;
|
||
}
|
||
|
||
const blob = new Blob([reportContent], {type: 'text/markdown'});
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = `运营周报_${document.getElementById('week').value}.md`;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
URL.revokeObjectURL(url);
|
||
}
|
||
|
||
// 页面加载时自动生成本周周报
|
||
window.addEventListener('load', function () {
|
||
generateCurrentWeekReport();
|
||
});
|
||
|
||
// 支持回车键生成报告
|
||
document.getElementById('week').addEventListener('keypress', function (e) {
|
||
if (e.key === 'Enter') {
|
||
generateReport();
|
||
}
|
||
});
|
||
|
||
// 使用专业的Markdown解析器解析Markdown文本,支持表格
|
||
function parseMarkdownWithTables(markdown) {
|
||
if (typeof MarkdownParser !== 'undefined' && typeof MergeTableParser !== 'undefined') {
|
||
const parser = new MarkdownParser();
|
||
return parser.parseFull(markdown);
|
||
} else {
|
||
// 回退到简单的markdown渲染
|
||
return markdownToHtml(markdown);
|
||
}
|
||
} |