/** * 日报展示系统 * 功能:从URL获取日报数据,解析并以美观的方式展示 * 部署于:supbi.pages.dev */ import React, { useEffect, useState } from 'react'; import './daily_report.css'; interface Task { stage: string; content: string; status: 'done' | 'on going'; } interface DailyReportItem { date: string; summary: string; tasks?: Task[]; } const DailyReport: React.FC = () => { const [reportData, setReportData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { // 从URL参数中获取数据 const urlParams = new URLSearchParams(window.location.search); const dataParam = urlParams.get('data'); if (!dataParam) { // 如果URL中没有数据参数,尝试从默认路径加载 const response = await fetch('/daily_report.json'); if (!response.ok) { throw new Error('无法加载日报数据'); } const data = await response.json(); processReportData(data); } else { // 解码URL参数中的数据 try { const decodedData = JSON.parse(decodeURIComponent(dataParam)); processReportData(decodedData); } catch (e) { throw new Error('无效的日报数据格式'); } } } catch (err) { setError(err instanceof Error ? err.message : '加载数据时出错'); } finally { setLoading(false); } }; fetchData(); }, []); // 处理报告数据,解析任务 const processReportData = (data: DailyReportItem[]) => { const processedData = data.map(item => { // 解析summary中的任务 const tasks: Task[] = []; const summaryLines = item.summary.split(';').map(line => line.trim()); summaryLines.forEach(line => { if (!line) return; // 提取阶段标记 "[📋需求]"等 const stageMatch = line.match(/\[(.*?)\]/); const stage = stageMatch ? stageMatch[0] : ''; // 提取状态 "[done]" 或 "[on going]" const statusMatch = line.match(/\[(done|on going)\]/); const status = statusMatch ? (statusMatch[1] as 'done' | 'on going') : 'on going'; // 提取内容(去除阶段标记和状态标记) let content = line.replace(/\[(.*?)\]/, '').trim(); content = content.replace(/\[(done|on going)\]/, '').trim(); tasks.push({ stage, content, status }); }); return { ...item, tasks }; }); // 按日期排序(最新的在前面) processedData.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); setReportData(processedData); }; // 渲染任务状态标记 const renderStatusBadge = (status: string) => { return status === 'done' ? 完成 : 进行中; }; if (loading) return
加载中...
; if (error) return
{error}
; return (

项目日报

supbi.pages.dev

{reportData.map((item, index) => (
{formatDate(item.date)}
{item.tasks?.map((task, taskIndex) => (
{task.stage}
{task.content}
{renderStatusBadge(task.status)}
))}
))}
); }; // 格式化日期显示 const formatDate = (dateString: string) => { const date = new Date(dateString); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][date.getDay()]; return `${year}年${month}月${day}日 ${weekday}`; }; export default DailyReport;