一行代码不写,就能让DeepSeek生成学生成长档案管理器!

今天继续介绍DeepSeek的“不会编程也能做应用”的事情。之前介绍的都是一些相对较小众的的东西,今天想折腾一个大一点的,给大家打个样。比如,让DeepSeek做一个班级学生成长档案管理系统。

是的,胆子就是这么大。这么专业的东西敢让DeepSeek做!做出来的东西居然还能用!

DeepSeek的野心完全藏不住了!想用一下试试?下面给你地址——

https://www.32kw.com/view/ebce066:一行代码不写,就能让DeepSeek生成学生成长档案管理器!

那么,用的是什么提示词呢?大家都知道,这个东西我也不知道怎么做,于是反手就甩给DeepSeek,让他帮我想提示词,等他想出来后我再改改。

下面是第一次提示词全文

等到DeepSeek给我答案后,我又稍作了修改,形成了最终的提示词。

你是H5开发专家和教育管理专家,请设计一个完整的班级学生成长档案管理H5单页应用。该应用将帮助班主任高效管理6年(12个学期)的学生数据、成绩记录和分析报告。请按以下要求生成独立的H5页面应用(即单个H5网页),强烈建议优先使用优秀的第三方前端js组件和CSS库,以减少代码量,但使用第三方库时禁止使用cdn.jsdelivr.net的库文件,优先使用BootCDN、Staticfile CDN和unpkg的库文件。 ## 技术选型建议 1. **UI框架**:使用Bootstrap 5(来自BootCDN)构建响应式界面 2. **数据处理**:使用Vue.js 3(来自unpkg)实现数据绑定和交互 3. **表格组件**:采用Tabulator.js(来自Staticfile CDN)处理学生名单和成绩展示 4. **图表库**:使用Chart.js(来自unpkg)进行成绩统计分析可视化 5. **文件处理**:SheetJS(来自unpkg)处理Excel导入导出 6. **PDF生成**:jsPDF(来自unpkg)创建学生报告单 7. 无后端交互,全前端,数据从本地手动加载本地Excel文件 ## 核心功能模块 ### 1. 学生名单管理 – 支持Excel批量导入学生基本信息(姓名、学号、性别等) – 增删改查单个学生信息 – 按学期分类展示(1-12学期标签页) – 支持学生升学/留级等状态变更 ### 2. 成绩管理 – 多学期成绩存储结构(12学期独立数据) – 支持Excel批量导入各科成绩 – 单科/多科成绩录入界面 – 成绩异常值自动检测提醒 ### 3. 统计分析 – 单科成绩分析(平均分、最高分、分数段分布) – 学生个人成绩趋势图(跨学期对比) – 班级成绩排名与进步分析 – 多科目成绩相关性分析 ### 4. 报告生成 – 自定义报告模板设计器 – 自动生成学生个人学期报告(含各科成绩、评语、图表) – 批量生成全班报告单 – PDF导出功能 ## 界面设计建议 1. **响应式布局**:适配电脑、平板和手机 2. **数据看板**:首页展示班级关键指标 3. **导航结构**:左侧菜单+顶部学期切换 4. **操作流程**:清晰的导入-处理-分析-导出工作流 ## 安全与性能 1. 纯前端实现,数据存储在浏览器IndexedDB中 2. 定期数据导出提醒功能 3. 大数据量下的性能优化(虚拟滚动、分页加载) ## 开发建议 1. 采用模块化开发,保持代码结构清晰 2. 实现完善的错误处理和用户引导 3. 添加操作日志记录关键动作

由于众所周知的原因,经过多次中断生成以后,生成了这样的代码,一共有3391行。下面我把代码都给你

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>刚哥帮EDU@班级学生成长档案管理系统</title>
    <!-- Bootstrap 5 CSS -->
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
    <!-- Tabulator CSS -->
    <link href="https://cdn.staticfile.org/tabulator/5.4.3/css/tabulator.min.css" rel="stylesheet">
    <!-- Font Awesome -->
    <link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <style>
        :root {
            --primary-color: #3498db;
            --secondary-color: #2ecc71;
            --danger-color: #e74c3c;
            --warning-color: #f39c12;
            --info-color: #9b59b6;
        }

        body {
            font-family: 'Microsoft YaHei', sans-serif;
            background-color: #f8f9fa;
        }

        .sidebar {
            height: 100vh;
            background: linear-gradient(135deg, #2c3e50, #34495e);
            color: white;
            position: fixed;
            padding-top: 20px;
            box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
            transition: all 0.3s;
            z-index: 1000;
        }

        .sidebar .nav-link {
            color: rgba(255, 255, 255, 0.8);
            margin-bottom: 5px;
            border-radius: 5px;
            padding: 10px 15px;
            transition: all 0.3s;
        }

        .sidebar .nav-link:hover, .sidebar .nav-link.active {
            background-color: rgba(255, 255, 255, 0.1);
            color: white;
        }

        .sidebar .nav-link i {
            margin-right: 10px;
            width: 20px;
            text-align: center;
        }

        .main-content {
            margin-left: 250px;
            padding: 20px;
            transition: all 0.3s;
        }

        .card {
            border-radius: 10px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            margin-bottom: 20px;
            border: none;
        }

        .card-header {
            background-color: white;
            border-bottom: 1px solid rgba(0, 0, 0, 0.1);
            font-weight: bold;
            border-radius: 10px 10px 0 0 !important;
        }

        .semester-tabs {
            background-color: white;
            border-radius: 10px;
            padding: 15px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
        }

        .nav-tabs .nav-link {
            border: none;
            color: #555;
            font-weight: 500;
            padding: 8px 15px;
        }

        .nav-tabs .nav-link.active {
            color: var(--primary-color);
            border-bottom: 3px solid var(--primary-color);
            background-color: transparent;
        }

        .dashboard-card {
            border-left: 4px solid;
            transition: transform 0.3s;
        }

        .dashboard-card:hover {
            transform: translateY(-5px);
        }

        .card-primary {
            border-left-color: var(--primary-color);
        }

        .card-success {
            border-left-color: var(--secondary-color);
        }

        .card-danger {
            border-left-color: var(--danger-color);
        }

        .card-warning {
            border-left-color: var(--warning-color);
        }

        .card-info {
            border-left-color: var(--info-color);
        }

        .btn-primary {
            background-color: var(--primary-color);
            border-color: var(--primary-color);
        }

        .btn-success {
            background-color: var(--secondary-color);
            border-color: var(--secondary-color);
        }

        .btn-danger {
            background-color: var(--danger-color);
            border-color: var(--danger-color);
        }

        .btn-warning {
            background-color: var(--warning-color);
            border-color: var(--warning-color);
        }

        .btn-info {
            background-color: var(--info-color);
            border-color: var(--info-color);
        }

        .badge-primary {
            background-color: var(--primary-color);
        }

        .badge-success {
            background-color: var(--secondary-color);
        }

        .badge-danger {
            background-color: var(--danger-color);
        }

        .badge-warning {
            background-color: var(--warning-color);
        }

        .badge-info {
            background-color: var(--info-color);
        }

        .progress {
            height: 10px;
            border-radius: 5px;
        }

        .progress-bar {
            background-color: var(--primary-color);
        }

        .student-avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            object-fit: cover;
            background-color: #eee;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            color: #555;
        }

        .action-buttons .btn {
            padding: 5px 10px;
            font-size: 12px;
            margin-right: 5px;
        }

        .tabulator {
            border-radius: 10px;
            overflow: hidden;
        }

        .tabulator .tabulator-header {
            background-color: #f8f9fa;
            font-weight: bold;
        }

        .tabulator .tabulator-tableHolder {
            background-color: white;
        }

        .tabulator-row.tabulator-selectable:hover {
            background-color: #f0f7ff !important;
        }

        .tabulator-row.tabulator-row-even {
            background-color: #f9f9f9;
        }

        .modal-content {
            border-radius: 15px;
            overflow: hidden;
        }

        .form-control, .form-select {
            border-radius: 8px;
            padding: 10px 15px;
        }

        .form-floating>label {
            padding: 10px 15px;
        }

        .toast-container {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 1100;
        }

        .chart-container {
            position: relative;
            height: 300px;
            margin-bottom: 20px;
        }

        .sidebar-collapsed {
            width: 80px;
            overflow: hidden;
        }

        .sidebar-collapsed .nav-link span {
            display: none;
        }

        .sidebar-collapsed .nav-link i {
            margin-right: 0;
            font-size: 1.2rem;
        }

        .sidebar-collapsed .sidebar-brand span {
            display: none;
        }

        .sidebar-collapsed + .main-content {
            margin-left: 80px;
        }

        .sidebar-toggle {
            position: fixed;
            left: 235px;
            top: 10px;
            z-index: 1100;
            background-color: white;
            border-radius: 50%;
            width: 30px;
            height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
            cursor: pointer;
            transition: all 0.3s;
        }

        .sidebar-collapsed .sidebar-toggle {
            left: 65px;
        }

        @media (max-width: 992px) {
            .sidebar {
                left: -250px;
            }

            .sidebar-collapsed {
                left: 0;
                width: 80px;
            }

            .main-content {
                margin-left: 0;
            }

            .sidebar-toggle {
                left: 10px;
            }

            .sidebar-collapsed .sidebar-toggle {
                left: 10px;
            }
        }

        .drag-drop-area {
            border: 2px dashed #ccc;
            border-radius: 10px;
            padding: 30px;
            text-align: center;
            background-color: #f9f9f9;
            cursor: pointer;
            transition: all 0.3s;
        }

        .drag-drop-area:hover {
            border-color: var(--primary-color);
            background-color: #f0f7ff;
        }

        .drag-drop-area.active {
            border-color: var(--primary-color);
            background-color: #e6f2ff;
        }

        .report-template {
            border: 1px solid #eee;
            border-radius: 10px;
            padding: 15px;
            margin-bottom: 15px;
            background-color: white;
            transition: all 0.3s;
            cursor: pointer;
        }

        .report-template:hover {
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
            transform: translateY(-3px);
        }

        .report-template.active {
            border-color: var(--primary-color);
            background-color: #f0f7ff;
        }

        .log-item {
            padding: 10px 15px;
            border-bottom: 1px solid #eee;
            font-size: 14px;
        }

        .log-item:last-child {
            border-bottom: none;
        }

        .log-time {
            font-size: 12px;
            color: #777;
        }

        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: #777;
        }

        .empty-state i {
            font-size: 50px;
            margin-bottom: 20px;
            color: #ddd;
        }
    </style>
</head>
<body>
    <div id="app">
        <!-- 侧边栏导航 -->
        <div class="sidebar" :class="{ 'sidebar-collapsed': isSidebarCollapsed }">
            <div class="sidebar-brand p-3 mb-4 d-flex align-items-center">
                <i class="fas fa-graduation-cap me-3 fs-4"></i>
                <span class="fs-5 fw-bold">成长档案系统</span>
            </div>
            <ul class="nav flex-column">
                <li class="nav-item">
                    <a class="nav-link active" href="#" @click="changeTab('dashboard')">
                        <i class="fas fa-tachometer-alt"></i>
                        <span>数据看板</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" @click="changeTab('students')">
                        <i class="fas fa-users"></i>
                        <span>学生管理</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" @click="changeTab('grades')">
                        <i class="fas fa-book"></i>
                        <span>成绩管理</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" @click="changeTab('analysis')">
                        <i class="fas fa-chart-bar"></i>
                        <span>统计分析</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" @click="changeTab('reports')">
                        <i class="fas fa-file-pdf"></i>
                        <span>报告生成</span>
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#" @click="changeTab('settings')">
                        <i class="fas fa-cog"></i>
                        <span>系统设置</span>
                    </a>
                </li>
            </ul>
        </div>

        <div class="sidebar-toggle" @click="toggleSidebar">
            <i class="fas" :class="isSidebarCollapsed ? 'fa-chevron-right' : 'fa-chevron-left'"></i>
        </div>

        <!-- 主内容区 -->
        <div class="main-content">
            <!-- 顶部学期导航 -->
            <div class="d-flex justify-content-between align-items-center mb-4">
                <h4 class="mb-0">{{ currentTabName }}</h4>
                <div class="semester-tabs">
                    <ul class="nav nav-tabs">
                        <li class="nav-item" v-for="semester in 12" :key="semester">
                            <a class="nav-link" :class="{ 'active': currentSemester === semester }" 
                               href="#" @click="changeSemester(semester)">
                                第{{ semester }}学期
                            </a>
                        </li>
                    </ul>
                </div>
            </div>

            <!-- 数据看板 -->
            <div v-if="currentTab === 'dashboard'" class="tab-content">
                <div class="row">
                    <div class="col-md-3">
                        <div class="card dashboard-card card-primary">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h6 class="text-muted mb-2">班级人数</h6>
                                        <h3 class="mb-0">{{ studentCount }}</h3>
                                    </div>
                                    <div class="bg-primary bg-opacity-10 p-3 rounded">
                                        <i class="fas fa-users text-primary"></i>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card dashboard-card card-success">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h6 class="text-muted mb-2">平均成绩</h6>
                                        <h3 class="mb-0">{{ averageGrade }}</h3>
                                    </div>
                                    <div class="bg-success bg-opacity-10 p-3 rounded">
                                        <i class="fas fa-book text-success"></i>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card dashboard-card card-warning">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h6 class="text-muted mb-2">最高分</h6>
                                        <h3 class="mb-0">{{ maxGrade }}</h3>
                                    </div>
                                    <div class="bg-warning bg-opacity-10 p-3 rounded">
                                        <i class="fas fa-star text-warning"></i>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card dashboard-card card-danger">
                            <div class="card-body">
                                <div class="d-flex justify-content-between align-items-center">
                                    <div>
                                        <h6 class="text-muted mb-2">最低分</h6>
                                        <h3 class="mb-0">{{ minGrade }}</h3>
                                    </div>
                                    <div class="bg-danger bg-opacity-10 p-3 rounded">
                                        <i class="fas fa-exclamation-triangle text-danger"></i>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row mt-4">
                    <div class="col-md-8">
                        <div class="card">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <span>成绩趋势分析</span>
                                <div>
                                    <select class="form-select form-select-sm" style="width: 150px;" v-model="trendSubject">
                                        <option value="all">全部科目</option>
                                        <option v-for="subject in subjects" :value="subject">{{ subject }}</option>
                                    </select>
                                </div>
                            </div>
                            <div class="card-body">
                                <div class="chart-container">
                                    <canvas id="trendChart"></canvas>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="card">
                            <div class="card-header">
                                <span>成绩分布</span>
                            </div>
                            <div class="card-body">
                                <div class="chart-container">
                                    <canvas id="distributionChart"></canvas>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row mt-4">
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header">
                                <span>操作日志</span>
                            </div>
                            <div class="card-body p-0">
                                <div v-if="logs.length === 0" class="empty-state">
                                    <i class="fas fa-clipboard-list"></i>
                                    <p>暂无操作记录</p>
                                </div>
                                <div v-else>
                                    <div class="log-item" v-for="log in logs.slice(0, 5)" :key="log.id">
                                        <div class="d-flex justify-content-between">
                                            <span>{{ log.action }}</span>
                                            <span class="log-time">{{ formatTime(log.time) }}</span>
                                        </div>
                                    </div>
                                    <div class="p-3 text-center" v-if="logs.length > 5">
                                        <button class="btn btn-sm btn-outline-primary" @click="viewAllLogs">查看全部</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header">
                                <span>数据备份</span>
                            </div>
                            <div class="card-body">
                                <p>上次备份时间: {{ lastBackupTime || '暂无备份' }}</p>
                                <div class="d-flex gap-2">
                                    <button class="btn btn-primary" @click="exportData">
                                        <i class="fas fa-download me-2"></i>导出数据
                                    </button>
                                    <button class="btn btn-outline-secondary" @click="importData">
                                        <i class="fas fa-upload me-2"></i>导入数据
                                    </button>
                                </div>
                                <div class="alert alert-warning mt-3">
                                    <i class="fas fa-exclamation-triangle me-2"></i>
                                    建议定期导出数据备份,防止数据丢失
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 学生管理 -->
            <div v-if="currentTab === 'students'" class="tab-content">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <span>学生名单管理</span>
                        <div>
                            <button class="btn btn-primary btn-sm" @click="showAddStudentModal">
                                <i class="fas fa-plus me-1"></i>添加学生
                            </button>
                            <button class="btn btn-success btn-sm ms-2" @click="showImportModal('students')">
                                <i class="fas fa-file-import me-1"></i>Excel导入
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div id="studentsTable"></div>
                    </div>
                </div>
            </div>

            <!-- 成绩管理 -->
            <div v-if="currentTab === 'grades'" class="tab-content">
                <div class="card">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <span>成绩管理</span>
                        <div>
                            <button class="btn btn-primary btn-sm" @click="showAddGradeModal">
                                <i class="fas fa-plus me-1"></i>添加成绩
                            </button>
                            <button class="btn btn-success btn-sm ms-2" @click="showImportModal('grades')">
                                <i class="fas fa-file-import me-1"></i>Excel导入
                            </button>
                            <button class="btn btn-info btn-sm ms-2" @click="exportGradeExcel">
                                <i class="fas fa-file-export me-1"></i>Excel导出
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="alert alert-warning" v-if="gradeWarnings.length > 0">
                            <i class="fas fa-exclamation-triangle me-2"></i>
                            <strong>发现 {{ gradeWarnings.length }} 条成绩异常:</strong>
                            <ul class="mb-0 mt-2">
                                <li v-for="warning in gradeWarnings" :key="warning.id">
                                    {{ warning.message }}
                                </li>
                            </ul>
                        </div>
                        <div id="gradesTable"></div>
                    </div>
                </div>
            </div>

            <!-- 统计分析 -->
            <div v-if="currentTab === 'analysis'" class="tab-content">
                <div class="row">
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <span>单科成绩分析</span>
                                <select class="form-select form-select-sm" style="width: 150px;" v-model="analysisSubject">
                                    <option v-for="subject in subjects" :value="subject">{{ subject }}</option>
                                </select>
                            </div>
                            <div class="card-body">
                                <div class="row mb-4">
                                    <div class="col-md-4">
                                        <div class="d-flex align-items-center">
                                            <div class="bg-primary bg-opacity-10 p-2 rounded me-3">
                                                <i class="fas fa-calculator text-primary"></i>
                                            </div>
                                            <div>
                                                <small class="text-muted">平均分</small>
                                                <h5 class="mb-0">{{ subjectStats.avg || '--' }}</h5>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="d-flex align-items-center">
                                            <div class="bg-success bg-opacity-10 p-2 rounded me-3">
                                                <i class="fas fa-arrow-up text-success"></i>
                                            </div>
                                            <div>
                                                <small class="text-muted">最高分</small>
                                                <h5 class="mb-0">{{ subjectStats.max || '--' }}</h5>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="d-flex align-items-center">
                                            <div class="bg-danger bg-opacity-10 p-2 rounded me-3">
                                                <i class="fas fa-arrow-down text-danger"></i>
                                            </div>
                                            <div>
                                                <small class="text-muted">最低分</small>
                                                <h5 class="mb-0">{{ subjectStats.min || '--' }}</h5>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="chart-container">
                                    <canvas id="subjectAnalysisChart"></canvas>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <span>学生进步分析</span>
                                <select class="form-select form-select-sm" style="width: 150px;" v-model="progressStudent">
                                    <option v-for="student in students" :value="student.id">{{ student.name }}</option>
                                </select>
                            </div>
                            <div class="card-body">
                                <div class="row mb-4">
                                    <div class="col-md-6">
                                        <div class="d-flex align-items-center">
                                            <div class="bg-info bg-opacity-10 p-2 rounded me-3">
                                                <i class="fas fa-chart-line text-info"></i>
                                            </div>
                                            <div>
                                                <small class="text-muted">进步幅度</small>
                                                <h5 class="mb-0">{{ studentProgress.rate || '--' }}%</h5>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <div class="d-flex align-items-center">
                                            <div class="bg-warning bg-opacity-10 p-2 rounded me-3">
                                                <i class="fas fa-medal text-warning"></i>
                                            </div>
                                            <div>
                                                <small class="text-muted">班级排名</small>
                                                <h5 class="mb-0">{{ studentProgress.rank || '--' }}</h5>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="chart-container">
                                    <canvas id="studentProgressChart"></canvas>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row mt-4">
                    <div class="col-md-12">
                        <div class="card">
                            <div class="card-header">
                                <span>科目相关性分析</span>
                            </div>
                            <div class="card-body">
                                <div class="chart-container" style="height: 400px;">
                                    <canvas id="correlationChart"></canvas>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 报告生成 -->
            <div v-if="currentTab === 'reports'" class="tab-content">
                <div class="row">
                    <div class="col-md-4">
                        <div class="card">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <span>报告模板</span>
                                <button class="btn btn-primary btn-sm" @click="showAddTemplateModal">
                                    <i class="fas fa-plus me-1"></i>新建模板
                                </button>
                            </div>
                            <div class="card-body">
                                <div class="report-template" 
                                     v-for="template in reportTemplates" 
                                     :key="template.id"
                                     :class="{ 'active': selectedTemplate === template.id }"
                                     @click="selectTemplate(template.id)">
                                    <h6>{{ template.name }}</h6>
                                    <small class="text-muted">最后修改: {{ formatTime(template.updatedAt) }}</small>
                                </div>
                                <div v-if="reportTemplates.length === 0" class="empty-state">
                                    <i class="fas fa-file-alt"></i>
                                    <p>暂无报告模板</p>
                                    <button class="btn btn-primary btn-sm" @click="showAddTemplateModal">
                                        <i class="fas fa-plus me-1"></i>创建第一个模板
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-8">
                        <div class="card">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <span>报告生成器</span>
                                <div v-if="selectedTemplate">
                                    <button class="btn btn-outline-secondary btn-sm" @click="editTemplate">
                                        <i class="fas fa-edit me-1"></i>编辑模板
                                    </button>
                                    <button class="btn btn-success btn-sm ms-2" @click="generateReport">
                                        <i class="fas fa-file-pdf me-1"></i>生成报告
                                    </button>
                                </div>
                            </div>
                            <div class="card-body">
                                <div v-if="!selectedTemplate" class="empty-state">
                                    <i class="fas fa-file-pdf"></i>
                                    <p>请从左侧选择一个模板</p>
                                </div>
                                <div v-else>
                                    <div class="mb-3">
                                        <label class="form-label">选择学生</label>
                                        <select class="form-select" v-model="reportStudent">
                                            <option v-for="student in students" :value="student.id">{{ student.name }} ({{ student.id }})</option>
                                        </select>
                                    </div>
                                    <div class="mb-3">
                                        <label class="form-label">选择学期</label>
                                        <select class="form-select" v-model="reportSemester">
                                            <option v-for="semester in 12" :value="semester">第{{ semester }}学期</option>
                                        </select>
                                    </div>
                                    <div class="mb-3">
                                        <label class="form-label">报告预览</label>
                                        <div class="border p-3" style="min-height: 300px; background-color: white;">
                                            <h5 class="text-center mb-4">{{ getTemplate(selectedTemplate).name }}</h5>
                                            <div v-html="previewReportContent"></div>
                                        </div>
                                    </div>
                                    <div class="d-flex justify-content-between">
                                        <button class="btn btn-outline-primary" @click="batchGenerateReports">
                                            <i class="fas fa-bolt me-1"></i>批量生成全班报告
                                        </button>
                                        <button class="btn btn-primary" @click="generateReport">
                                            <i class="fas fa-download me-1"></i>下载PDF报告
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 系统设置 -->
            <div v-if="currentTab === 'settings'" class="tab-content">
                <div class="row">
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header">
                                <span>科目设置</span>
                            </div>
                            <div class="card-body">
                                <div class="mb-3">
                                    <label class="form-label">当前科目</label>
                                    <div class="d-flex gap-2 mb-2">
                                        <input type="text" class="form-control" v-model="newSubject" placeholder="输入新科目名称">
                                        <button class="btn btn-primary" @click="addSubject">添加</button>
                                    </div>
                                    <div class="d-flex flex-wrap gap-2">
                                        <span class="badge bg-primary d-flex align-items-center" v-for="subject in subjects" :key="subject">
                                            {{ subject }}
                                            <button class="btn btn-sm p-0 ms-2" @click="removeSubject(subject)">
                                                <i class="fas fa-times text-white"></i>
                                            </button>
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header">
                                <span>系统设置</span>
                            </div>
                            <div class="card-body">
                                <div class="mb-3">
                                    <label class="form-label">班级名称</label>
                                    <input type="text" class="form-control" v-model="className">
                                </div>
                                <div class="mb-3">
                                    <label class="form-label">班主任</label>
                                    <input type="text" class="form-control" v-model="teacherName">
                                </div>
                                <div class="mb-3">
                                    <label class="form-label">学年设置</label>
                                    <input type="text" class="form-control" v-model="academicYear">
                                </div>
                                <button class="btn btn-primary" @click="saveSettings">保存设置</button>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row mt-4">
                    <div class="col-md-12">
                        <div class="card">
                            <div class="card-header">
                                <span>数据管理</span>
                            </div>
                            <div class="card-body">
                                <div class="alert alert-danger">
                                    <i class="fas fa-exclamation-triangle me-2"></i>
                                    <strong>危险操作</strong> - 以下操作将永久删除数据,请谨慎操作
                                </div>
                                <div class="d-flex gap-2">
                                    <button class="btn btn-outline-danger" @click="confirmClearData('students')">
                                        <i class="fas fa-trash me-1"></i>清空学生数据
                                    </button>
                                    <button class="btn btn-outline-danger" @click="confirmClearData('grades')">
                                        <i class="fas fa-trash me-1"></i>清空成绩数据
                                    </button>
                                    <button class="btn btn-outline-danger" @click="confirmClearData('all')">
                                        <i class="fas fa-trash me-1"></i>清空所有数据
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 添加学生模态框 -->
        <div class="modal fade" id="addStudentModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">{{ editStudentMode ? '编辑学生信息' : '添加新学生' }}</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="mb-3">
                            <label class="form-label">学号</label>
                            <input type="text" class="form-control" v-model="currentStudent.id" :disabled="editStudentMode">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">姓名</label>
                            <input type="text" class="form-control" v-model="currentStudent.name">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">性别</label>
                            <select class="form-select" v-model="currentStudent.gender">
                                <option value="男">男</option>
                                <option value="女">女</option>
                            </select>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">出生日期</label>
                            <input type="date" class="form-control" v-model="currentStudent.birthday">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">联系电话</label>
                            <input type="text" class="form-control" v-model="currentStudent.phone">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">家庭住址</label>
                            <input type="text" class="form-control" v-model="currentStudent.address">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">状态</label>
                            <select class="form-select" v-model="currentStudent.status">
                                <option value="在读">在读</option>
                                <option value="休学">休学</option>
                                <option value="退学">退学</option>
                                <option value="毕业">毕业</option>
                            </select>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                        <button type="button" class="btn btn-primary" @click="saveStudent">保存</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 添加成绩模态框 -->
        <div class="modal fade" id="addGradeModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">{{ editGradeMode ? '编辑成绩' : '添加成绩' }}</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="mb-3">
                            <label class="form-label">学生</label>
                            <select class="form-select" v-model="currentGrade.studentId">
                                <option v-for="student in students" :value="student.id">{{ student.name }} ({{ student.id }})</option>
                            </select>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">学期</label>
                            <select class="form-select" v-model="currentGrade.semester">
                                <option v-for="semester in 12" :value="semester">第{{ semester }}学期</option>
                            </select>
                        </div>
                        <div class="mb-3" v-for="subject in subjects" :key="subject">
                            <label class="form-label">{{ subject }}成绩</label>
                            <input type="number" class="form-control" v-model="currentGrade.subjects[subject]" min="0" max="100" step="0.1">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">评语</label>
                            <textarea class="form-control" v-model="currentGrade.comment" rows="3"></textarea>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                        <button type="button" class="btn btn-primary" @click="saveGrade">保存</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 导入数据模态框 -->
        <div class="modal fade" id="importModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">{{ importType === 'students' ? '导入学生数据' : '导入成绩数据' }}</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="alert alert-info">
                            <i class="fas fa-info-circle me-2"></i>
                            请下载模板文件,按照格式填写数据后导入
                            <a href="#" @click.prevent="downloadTemplate" class="ms-2">下载模板</a>
                        </div>
                        <div class="drag-drop-area" 
                             @dragover.prevent="dragOver = true" 
                             @dragleave="dragOver = false"
                             @drop.prevent="handleFileDrop"
                             :class="{ 'active': dragOver }">
                            <i class="fas fa-file-excel fa-3x mb-3 text-success"></i>
                            <h5>拖放Excel文件到此处</h5>
                            <p class="text-muted">或</p>
                            <input type="file" id="fileInput" class="d-none" accept=".xlsx,.xls" @change="handleFileSelect">
                            <label for="fileInput" class="btn btn-primary">
                                <i class="fas fa-folder-open me-2"></i>选择文件
                            </label>
                        </div>
                        <div class="alert alert-warning mt-3" v-if="importType === 'grades'">
                            <i class="fas fa-exclamation-triangle me-2"></i>
                            注意:导入成绩数据会覆盖同学生同学期的已有成绩
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                        <button type="button" class="btn btn-primary" @click="confirmImport" :disabled="!importFile">导入</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 添加模板模态框 -->
        <div class="modal fade" id="addTemplateModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog modal-lg">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">{{ editTemplateMode ? '编辑报告模板' : '新建报告模板' }}</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="mb-3">
                            <label class="form-label">模板名称</label>
                            <input type="text" class="form-control" v-model="currentTemplate.name">
                        </div>
                        <div class="mb-3">
                            <label class="form-label">模板内容</label>
                            <div class="border p-2 mb-2">
                                <button class="btn btn-sm btn-outline-secondary me-2" @click="insertVariable('studentName')">
                                    <i class="fas fa-user me-1"></i>学生姓名
                                </button>
                                <button class="btn btn-sm btn-outline-secondary me-2" @click="insertVariable('semester')">
                                    <i class="fas fa-calendar me-1"></i>学期
                                </button>
                                <button class="btn btn-sm btn-outline-secondary me-2" @click="insertVariable('gradesTable')">
                                    <i class="fas fa-table me-1"></i>成绩表格
                                </button>
                                <button class="btn btn-sm btn-outline-secondary me-2" @click="insertVariable('progressChart')">
                                    <i class="fas fa-chart-line me-1"></i>进步图表
                                </button>
                            </div>
                            <textarea class="form-control" v-model="currentTemplate.content" rows="10"></textarea>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">预览</label>
                            <div class="border p-3" style="min-height: 200px; background-color: white;">
                                <div v-html="previewTemplateContent"></div>
                            </div>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                        <button type="button" class="btn btn-primary" @click="saveTemplate">保存</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 确认清除数据模态框 -->
        <div class="modal fade" id="confirmClearModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header bg-danger text-white">
                        <h5 class="modal-title">确认清除数据</h5>
                        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="alert alert-danger">
                            <i class="fas fa-exclamation-triangle me-2"></i>
                            您确定要清除{{ clearDataType === 'students' ? '所有学生数据' : clearDataType === 'grades' ? '所有成绩数据' : '所有数据' }}吗?此操作不可撤销!
                        </div>
                        <div class="form-check mb-3">
                            <input class="form-check-input" type="checkbox" id="confirmCheck" v-model="confirmChecked">
                            <label class="form-check-label" for="confirmCheck">
                                我确认要删除数据
                            </label>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                        <button type="button" class="btn btn-danger" @click="clearData" :disabled="!confirmChecked">确认清除</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 查看所有日志模态框 -->
        <div class="modal fade" id="allLogsModal" tabindex="-1" aria-hidden="true">
            <div class="modal-dialog modal-lg">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">操作日志</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="log-item border-bottom" v-for="log in logs" :key="log.id">
                            <div class="d-flex justify-content-between">
                                <span>{{ log.action }}</span>
                                <span class="log-time">{{ formatTime(log.time) }}</span>
                            </div>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                    </div>
                </div>
            </div>
        </div>

        <!-- Toast通知 -->
        <div class="toast-container">
            <div class="toast align-items-center" :class="`text-bg-${toast.type}`" role="alert" aria-live="assertive" aria-atomic="true" v-if="toast.show">
                <div class="d-flex">
                    <div class="toast-body">
                        <i class="fas me-2" :class="toastIcon"></i>
                        {{ toast.message }}
                    </div>
                    <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close" @click="toast.show = false"></button>
                </div>
            </div>
        </div>
    </div>

    <!-- 第三方库 -->
    <!-- Vue 3 -->
    <script src="https://unpkg.com/vue@3.2.47/dist/vue.global.prod.js"></script>
    <!-- Bootstrap 5 JS -->
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.bundle.min.js"></script>
    <!-- Tabulator -->
    <script src="https://cdn.staticfile.org/tabulator/5.4.3/js/tabulator.min.js"></script>
    <!-- Chart.js -->
    <script src="https://unpkg.com/chart.js@4.2.1/dist/chart.umd.min.js"></script>
    <!-- SheetJS -->
    <script src="https://unpkg.com/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
    <!-- jsPDF -->
    <script src="https://unpkg.com/jspdf@2.5.1/dist/jspdf.umd.min.js"></script>
    <!-- 自动表格插件 -->
    <script src="https://unpkg.com/jspdf-autotable@3.5.28/dist/jspdf.plugin.autotable.min.js"></script>

    <script>
        const { createApp, ref, reactive, computed, onMounted, watch, nextTick } = Vue;

        // 生成UUID
        function generateId() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                const r = Math.random() * 16 | 0;
                const v = c === 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }

        // 格式化时间
        function formatTime(date) {
            if (!date) return '';
            const d = new Date(date);
            return `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')} ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
        }

        createApp({
            setup() {
                // 状态管理
                const isSidebarCollapsed = ref(false);
                const currentTab = ref('dashboard');
                const currentSemester = ref(1);
                const students = ref([]);
                const grades = ref([]);
                const reportTemplates = ref([]);
                const selectedTemplate = ref(null);
                const reportStudent = ref(null);
                const reportSemester = ref(1);
                const subjects = ref(['语文', '数学', '英语', '物理', '化学', '生物']);
                const className = ref('六年级一班');
                const teacherName = ref('张老师');
                const academicYear = ref('2022-2023');
                const logs = ref([]);
                const lastBackupTime = ref(null);
                const toast = reactive({
                    show: false,
                    message: '',
                    type: 'success'
                });

                // 当前操作对象
                const currentStudent = reactive({
                    id: '',
                    name: '',
                    gender: '男',
                    birthday: '',
                    phone: '',
                    address: '',
                    status: '在读'
                });

                const currentGrade = reactive({
                    id: '',
                    studentId: '',
                    semester: 1,
                    subjects: {},
                    comment: ''
                });

                const currentTemplate = reactive({
                    id: '',
                    name: '',
                    content: ''
                });

                // 模态框状态
                const editStudentMode = ref(false);
                const editGradeMode = ref(false);
                const editTemplateMode = ref(false);
                const importType = ref('students');
                const importFile = ref(null);
                const dragOver = ref(false);
                const clearDataType = ref('all');
                const confirmChecked = ref(false);

                // 分析相关状态
                const trendSubject = ref('all');
                const analysisSubject = ref('语文');
                const progressStudent = ref(null);

                // 表格实例
                const studentsTable = ref(null);
                const gradesTable = ref(null);

                // 图表实例
                const trendChart = ref(null);
                const distributionChart = ref(null);
                const subjectAnalysisChart = ref(null);
                const studentProgressChart = ref(null);
                const correlationChart = ref(null);

                // 计算属性
                const currentTabName = computed(() => {
                    const names = {
                        'dashboard': '数据看板',
                        'students': '学生管理',
                        'grades': '成绩管理',
                        'analysis': '统计分析',
                        'reports': '报告生成',
                        'settings': '系统设置'
                    };
                    return names[currentTab.value];
                });

                const studentCount = computed(() => {
                    return students.value.length;
                });

                const averageGrade = computed(() => {
                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    if (currentGrades.length === 0) return '--';

                    let total = 0;
                    let count = 0;

                    currentGrades.forEach(grade => {
                        Object.values(grade.subjects).forEach(score => {
                            if (score !== null && score !== undefined) {
                                total += parseFloat(score);
                                count++;
                            }
                        });
                    });

                    return count > 0 ? (total / count).toFixed(1) : '--';
                });

                const maxGrade = computed(() => {
                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    if (currentGrades.length === 0) return '--';

                    let max = -Infinity;

                    currentGrades.forEach(grade => {
                        Object.values(grade.subjects).forEach(score => {
                            if (score !== null && score !== undefined) {
                                const num = parseFloat(score);
                                if (num > max) max = num;
                            }
                        });
                    });

                    return max !== -Infinity ? max.toFixed(1) : '--';
                });

                const minGrade = computed(() => {
                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    if (currentGrades.length === 0) return '--';

                    let min = Infinity;

                    currentGrades.forEach(grade => {
                        Object.values(grade.subjects).forEach(score => {
                            if (score !== null && score !== undefined) {
                                const num = parseFloat(score);
                                if (num < min) min = num;
                            }
                        });
                    });

                    return min !== Infinity ? min.toFixed(1) : '--';
                });

                const gradeWarnings = computed(() => {
                    const warnings = [];

                    grades.value.forEach(grade => {
                        Object.entries(grade.subjects).forEach(([subject, score]) => {
                            if (score !== null && score !== undefined) {
                                const num = parseFloat(score);
                                if (num < 0 || num > 100) {
                                    const student = students.value.find(s => s.id === grade.studentId);
                                    warnings.push({
                                        id: `${grade.id}-${subject}`,
                                        message: `${student?.name || grade.studentId} 第${grade.semester}学期 ${subject}成绩异常: ${score}分`
                                    });
                                }
                            }
                        });
                    });

                    return warnings;
                });

                const subjectStats = computed(() => {
                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    if (currentGrades.length === 0) return {};

                    const subject = analysisSubject.value;
                    const scores = currentGrades.map(g => g.subjects[subject]).filter(s => s !== null && s !== undefined).map(s => parseFloat(s));

                    if (scores.length === 0) return {};

                    const sum = scores.reduce((a, b) => a + b, 0);
                    const avg = sum / scores.length;
                    const max = Math.max(...scores);
                    const min = Math.min(...scores);

                    // 分数段统计
                    const segments = [0, 60, 70, 80, 90, 100];
                    const segmentCounts = {};

                    for (let i = 0; i < segments.length - 1; i++) {
                        const lower = segments[i];
                        const upper = segments[i + 1];
                        const key = `${lower}-${upper}`;
                        segmentCounts[key] = scores.filter(s => s >= lower && s < upper).length;
                    }

                    // 特殊处理100分
                    segmentCounts['100'] = scores.filter(s => s === 100).length;

                    return {
                        avg: avg.toFixed(1),
                        max: max.toFixed(1),
                        min: min.toFixed(1),
                        segmentCounts
                    };
                });

                const studentProgress = computed(() => {
                    if (!progressStudent.value) return {};

                    const studentGrades = grades.value.filter(g => g.studentId === progressStudent.value);
                    if (studentGrades.length < 2) return {};

                    // 计算平均分变化
                    const firstSemester = Math.min(...studentGrades.map(g => g.semester));
                    const lastSemester = Math.max(...studentGrades.map(g => g.semester));

                    const firstGrade = studentGrades.find(g => g.semester === firstSemester);
                    const lastGrade = studentGrades.find(g => g.semester === lastSemester);

                    let firstAvg = 0;
                    let firstCount = 0;
                    Object.values(firstGrade.subjects).forEach(score => {
                        if (score !== null && score !== undefined) {
                            firstAvg += parseFloat(score);
                            firstCount++;
                        }
                    });
                    firstAvg = firstCount > 0 ? firstAvg / firstCount : 0;

                    let lastAvg = 0;
                    let lastCount = 0;
                    Object.values(lastGrade.subjects).forEach(score => {
                        if (score !== null && score !== undefined) {
                            lastAvg += parseFloat(score);
                            lastCount++;
                        }
                    });
                    lastAvg = lastCount > 0 ? lastAvg / lastCount : 0;

                    const rate = ((lastAvg - firstAvg) / firstAvg * 100).toFixed(1);

                    // 计算当前排名
                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    const averages = [];

                    currentGrades.forEach(grade => {
                        let sum = 0;
                        let count = 0;

                        Object.values(grade.subjects).forEach(score => {
                            if (score !== null && score !== undefined) {
                                sum += parseFloat(score);
                                count++;
                            }
                        });

                        if (count > 0) {
                            averages.push({
                                studentId: grade.studentId,
                                avg: sum / count
                            });
                        }
                    });

                    // 按平均分排序
                    averages.sort((a, b) => b.avg - a.avg);

                    const rank = averages.findIndex(a => a.studentId === progressStudent.value) + 1;

                    return {
                        rate,
                        rank
                    };
                });

                const previewTemplateContent = computed(() => {
                    if (!currentTemplate.content) return '请输入模板内容';

                    // 简单替换变量为示例文本
                    return currentTemplate.content
                        .replace(/\{\{studentName\}\}/g, '张三')
                        .replace(/\{\{semester\}\}/g, '第1学期')
                        .replace(/\{\{gradesTable\}\}/g, '<div class="alert alert-info">此处将显示成绩表格</div>')
                        .replace(/\{\{progressChart\}\}/g, '<div class="alert alert-info">此处将显示进步图表</div>');
                });

                const previewReportContent = computed(() => {
                    if (!selectedTemplate.value) return '';

                    const template = getTemplate(selectedTemplate.value);
                    if (!template) return '';

                    const student = students.value.find(s => s.id === reportStudent.value);
                    const grade = grades.value.find(g => g.studentId === reportStudent.value && g.semester === reportSemester.value);

                    if (!student || !grade) return template.content;

                    // 替换变量为实际内容
                    let content = template.content.replace(/\{\{studentName\}\}/g, student.name);
                    content = content.replace(/\{\{semester\}\}/g, `第${reportSemester.value}学期`);

                    // 生成成绩表格
                    if (content.includes('{{gradesTable}}')) {
                        let tableHtml = '<table class="table table-bordered mt-3"><thead><tr><th>科目</th><th>成绩</th></tr></thead><tbody>';

                        Object.entries(grade.subjects).forEach(([subject, score]) => {
                            tableHtml += `<tr><td>${subject}</td><td>${score || '--'}</td></tr>`;
                        });

                        tableHtml += '</tbody></table>';
                        content = content.replace(/\{\{gradesTable\}\}/g, tableHtml);
                    }

                    // 生成进步图表占位
                    if (content.includes('{{progressChart}}')) {
                        content = content.replace(/\{\{progressChart\}\}/g, '<div class="chart-container" style="height: 200px;"><canvas></canvas></div>');
                    }

                    return content;
                });

                const toastIcon = computed(() => {
                    const icons = {
                        'success': 'fa-check-circle',
                        'danger': 'fa-exclamation-circle',
                        'warning': 'fa-exclamation-triangle',
                        'info': 'fa-info-circle'
                    };
                    return icons[toast.type] || 'fa-info-circle';
                });

                // 方法
                const toggleSidebar = () => {
                    isSidebarCollapsed.value = !isSidebarCollapsed.value;
                };

                const changeTab = (tab) => {
                    currentTab.value = tab;

                    // 初始化相关组件
                    nextTick(() => {
                        if (tab === 'students' && !studentsTable.value) {
                            initStudentsTable();
                        } else if (tab === 'grades' && !gradesTable.value) {
                            initGradesTable();
                        } else if (tab === 'dashboard') {
                            renderCharts();
                        } else if (tab === 'analysis') {
                            renderAnalysisCharts();
                        }
                    });
                };

                const changeSemester = (semester) => {
                    currentSemester.value = semester;

                    if (currentTab.value === 'grades' && gradesTable.value) {
                        gradesTable.value.setData(getGradesForSemester(semester));
                    }

                    if (currentTab.value === 'dashboard') {
                        renderCharts();
                    }
                };

                const showToast = (message, type = 'success', duration = 3000) => {
                    toast.message = message;
                    toast.type = type;
                    toast.show = true;

                    if (duration > 0) {
                        setTimeout(() => {
                            toast.show = false;
                        }, duration);
                    }
                };

                const logAction = (action) => {
                    logs.value.unshift({
                        id: generateId(),
                        action,
                        time: new Date()
                    });

                    // 限制日志数量
                    if (logs.value.length > 100) {
                        logs.value.pop();
                    }

                    saveLogs();
                };

                const formatTime = (date) => {
                    return formatTime(date);
                };

                // 学生管理方法
                const showAddStudentModal = () => {
                    editStudentMode.value = false;
                    Object.assign(currentStudent, {
                        id: '',
                        name: '',
                        gender: '男',
                        birthday: '',
                        phone: '',
                        address: '',
                        status: '在读'
                    });

                    const modal = new bootstrap.Modal(document.getElementById('addStudentModal'));
                    modal.show();
                };

                const editStudent = (student) => {
                    editStudentMode.value = true;
                    Object.assign(currentStudent, JSON.parse(JSON.stringify(student)));

                    const modal = new bootstrap.Modal(document.getElementById('addStudentModal'));
                    modal.show();
                };

                const saveStudent = () => {
                    if (!currentStudent.id || !currentStudent.name) {
                        showToast('学号和姓名不能为空', 'danger');
                        return;
                    }

                    if (editStudentMode.value) {
                        // 更新学生
                        const index = students.value.findIndex(s => s.id === currentStudent.id);
                        if (index !== -1) {
                            students.value[index] = JSON.parse(JSON.stringify(currentStudent));
                            showToast('学生信息更新成功');
                            logAction(`更新学生信息: ${currentStudent.name}`);
                        }
                    } else {
                        // 检查学号是否已存在
                        if (students.value.some(s => s.id === currentStudent.id)) {
                            showToast('该学号已存在', 'danger');
                            return;
                        }

                        // 添加新学生
                        students.value.push(JSON.parse(JSON.stringify(currentStudent)));
                        showToast('学生添加成功');
                        logAction(`添加新学生: ${currentStudent.name}`);
                    }

                    saveStudents();
                    studentsTable.value.setData(students.value);

                    const modal = bootstrap.Modal.getInstance(document.getElementById('addStudentModal'));
                    modal.hide();
                };

                const deleteStudent = (studentId) => {
                    if (confirm('确定要删除这个学生吗?同时会删除该学生的所有成绩记录!')) {
                        const student = students.value.find(s => s.id === studentId);
                        students.value = students.value.filter(s => s.id !== studentId);

                        // 删除相关成绩
                        grades.value = grades.value.filter(g => g.studentId !== studentId);

                        saveStudents();
                        saveGrades();

                        if (studentsTable.value) {
                            studentsTable.value.setData(students.value);
                        }

                        if (gradesTable.value) {
                            gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                        }

                        showToast('学生删除成功');
                        logAction(`删除学生: ${student?.name || studentId}`);
                    }
                };

                const initStudentsTable = () => {
                    studentsTable.value = new Tabulator('#studentsTable', {
                        data: students.value,
                        layout: 'fitColumns',
                        responsiveLayout: true,
                        pagination: 'local',
                        paginationSize: 10,
                        paginationSizeSelector: [5, 10, 20, 50],
                        columns: [
                            {
                                title: '学号',
                                field: 'id',
                                sorter: 'string',
                                width: 120
                            },
                            {
                                title: '姓名',
                                field: 'name',
                                sorter: 'string',
                                formatter: (cell) => {
                                    const row = cell.getRow().getData();
                                    return `<div class="d-flex align-items-center">
                                        <div class="student-avatar me-2">${row.name.charAt(0)}</div>
                                        <span>${row.name}</span>
                                    </div>`;
                                }
                            },
                            {
                                title: '性别',
                                field: 'gender',
                                sorter: 'string',
                                width: 80
                            },
                            {
                                title: '状态',
                                field: 'status',
                                sorter: 'string',
                                width: 100,
                                formatter: (cell) => {
                                    const status = cell.getValue();
                                    let badgeClass = 'bg-secondary';

                                    if (status === '在读') badgeClass = 'bg-success';
                                    else if (status === '休学') badgeClass = 'bg-warning';
                                    else if (status === '退学') badgeClass = 'bg-danger';
                                    else if (status === '毕业') badgeClass = 'bg-info';

                                    return `<span class="badge ${badgeClass}">${status}</span>`;
                                }
                            },
                            {
                                title: '联系电话',
                                field: 'phone',
                                sorter: 'string'
                            },
                            {
                                title: '操作',
                                field: 'id',
                                width: 150,
                                formatter: (cell) => {
                                    const id = cell.getValue();
                                    return `<div class="action-buttons">
                                        <button class="btn btn-sm btn-outline-primary" onclick="app.editStudent(${JSON.stringify(cell.getRow().getData())})">
                                            <i class="fas fa-edit"></i>
                                        </button>
                                        <button class="btn btn-sm btn-outline-danger" onclick="app.deleteStudent('${id}')">
                                            <i class="fas fa-trash"></i>
                                        </button>
                                        <button class="btn btn-sm btn-outline-info" onclick="app.viewStudentDetails('${id}')">
                                            <i class="fas fa-info-circle"></i>
                                        </button>
                                    </div>`;
                                }
                            }
                        ]
                    });
                };

                const viewStudentDetails = (studentId) => {
                    const student = students.value.find(s => s.id === studentId);
                    if (!student) return;

                    alert(`学生详情:\n\n姓名: ${student.name}\n学号: ${student.id}\n性别: ${student.gender}\n出生日期: ${student.birthday || '无'}\n联系电话: ${student.phone || '无'}\n家庭住址: ${student.address || '无'}\n状态: ${student.status}`);
                };

                // 成绩管理方法
                const getGradesForSemester = (semester) => {
                    return grades.value.filter(g => g.semester === semester).map(grade => {
                        const student = students.value.find(s => s.id === grade.studentId);
                        return {
                            ...grade,
                            studentName: student?.name || '未知',
                            studentGender: student?.gender || '未知'
                        };
                    });
                };

                const showAddGradeModal = () => {
                    editGradeMode.value = false;
                    Object.assign(currentGrade, {
                        id: '',
                        studentId: students.value[0]?.id || '',
                        semester: currentSemester.value,
                        subjects: {},
                        comment: ''
                    });

                    // 初始化科目成绩
                    subjects.value.forEach(subject => {
                        currentGrade.subjects[subject] = '';
                    });

                    const modal = new bootstrap.Modal(document.getElementById('addGradeModal'));
                    modal.show();
                };

                const editGrade = (grade) => {
                    editGradeMode.value = true;
                    Object.assign(currentGrade, JSON.parse(JSON.stringify(grade)));

                    const modal = new bootstrap.Modal(document.getElementById('addGradeModal'));
                    modal.show();
                };

                const saveGrade = () => {
                    if (!currentGrade.studentId) {
                        showToast('请选择学生', 'danger');
                        return;
                    }

                    // 验证成绩
                    for (const [subject, score] of Object.entries(currentGrade.subjects)) {
                        if (score !== '' && (isNaN(score) || score < 0 || score > 100)) {
                            showToast(`${subject}成绩必须在0-100之间`, 'danger');
                            return;
                        }
                    }

                    if (editGradeMode.value) {
                        // 更新成绩
                        const index = grades.value.findIndex(g => g.id === currentGrade.id);
                        if (index !== -1) {
                            grades.value[index] = JSON.parse(JSON.stringify(currentGrade));
                            showToast('成绩更新成功');

                            const student = students.value.find(s => s.id === currentGrade.studentId);
                            logAction(`更新成绩: ${student?.name || currentGrade.studentId} 第${currentGrade.semester}学期`);
                        }
                    } else {
                        // 检查是否已存在该学生该学期的成绩
                        const exists = grades.value.some(g => g.studentId === currentGrade.studentId && g.semester === currentGrade.semester);

                        if (exists) {
                            showToast('该学生本学期的成绩已存在,请编辑现有记录', 'danger');
                            return;
                        }

                        // 添加新成绩
                        currentGrade.id = generateId();
                        grades.value.push(JSON.parse(JSON.stringify(currentGrade)));
                        showToast('成绩添加成功');

                        const student = students.value.find(s => s.id === currentGrade.studentId);
                        logAction(`添加成绩: ${student?.name || currentGrade.studentId} 第${currentGrade.semester}学期`);
                    }

                    saveGrades();

                    if (gradesTable.value) {
                        gradesTable.value.setData(getGradesForSemester(currentGrade.semester));
                    }

                    const modal = bootstrap.Modal.getInstance(document.getElementById('addGradeModal'));
                    modal.hide();
                };

                const deleteGrade = (gradeId) => {
                    if (confirm('确定要删除这条成绩记录吗?')) {
                        const grade = grades.value.find(g => g.id === gradeId);
                        grades.value = grades.value.filter(g => g.id !== gradeId);

                        saveGrades();

                        if (gradesTable.value) {
                            gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                        }

                        const student = students.value.find(s => s.id === grade?.studentId);
                        showToast('成绩删除成功');
                        logAction(`删除成绩: ${student?.name || grade?.studentId || '未知'} 第${grade?.semester || '未知'}学期`);
                    }
                };

                const initGradesTable = () => {
                    gradesTable.value = new Tabulator('#gradesTable', {
                        data: getGradesForSemester(currentSemester.value),
                        layout: 'fitColumns',
                        responsiveLayout: true,
                        pagination: 'local',
                        paginationSize: 10,
                        paginationSizeSelector: [5, 10, 20, 50],
                        columns: [
                            {
                                title: '学号',
                                field: 'studentId',
                                sorter: 'string',
                                width: 120
                            },
                            {
                                title: '姓名',
                                field: 'studentName',
                                sorter: 'string'
                            },
                            ...subjects.value.map(subject => ({
                                title: subject,
                                field: `subjects.${subject}`,
                                sorter: 'number',
                                width: 100,
                                formatter: (cell) => {
                                    const value = cell.getValue();
                                    if (value === null || value === undefined || value === '') return '--';

                                    const num = parseFloat(value);
                                    if (num < 60) return `<span class="text-danger">${num}</span>`;
                                    if (num >= 90) return `<span class="text-success">${num}</span>`;
                                    return num;
                                }
                            })),
                            {
                                title: '操作',
                                field: 'id',
                                width: 120,
                                formatter: (cell) => {
                                    const id = cell.getValue();
                                    return `<div class="action-buttons">
                                        <button class="btn btn-sm btn-outline-primary" onclick="app.editGrade(${JSON.stringify(cell.getRow().getData())})">
                                            <i class="fas fa-edit"></i>
                                        </button>
                                        <button class="btn btn-sm btn-outline-danger" onclick="app.deleteGrade('${id}')">
                                            <i class="fas fa-trash"></i>
                                        </button>
                                    </div>`;
                                }
                            }
                        ]
                    });
                };

                // 导入导出方法
                const showImportModal = (type) => {
                    importType.value = type;
                    importFile.value = null;
                    dragOver.value = false;

                    const modal = new bootstrap.Modal(document.getElementById('importModal'));
                    modal.show();
                };

                const handleFileDrop = (e) => {
                    dragOver.value = false;
                    const file = e.dataTransfer.files[0];
                    if (file) {
                        importFile.value = file;
                    }
                };

                const handleFileSelect = (e) => {
                    const file = e.target.files[0];
                    if (file) {
                        importFile.value = file;
                    }
                };

                const downloadTemplate = () => {
                    if (importType.value === 'students') {
                        // 学生模板
                        const templateData = [
                            ['学号', '姓名', '性别', '出生日期', '联系电话', '家庭住址', '状态'],
                            ['1001', '张三', '男', '2010-05-15', '13800138000', '北京市海淀区', '在读'],
                            ['1002', '李四', '女', '2010-08-22', '13900139000', '北京市朝阳区', '在读']
                        ];

                        const wb = XLSX.utils.book_new();
                        const ws = XLSX.utils.aoa_to_sheet(templateData);
                        XLSX.utils.book_append_sheet(wb, ws, '学生模板');
                        XLSX.writeFile(wb, '学生信息导入模板.xlsx');
                    } else {
                        // 成绩模板
                        const headers = ['学号', '学期', ...subjects.value, '评语'];
                        const templateData = [
                            headers,
                            ['1001', '1', '85', '92', '88', '90', '95', '89', '该生表现优秀'],
                            ['1002', '1', '78', '85', '82', '76', '80', '84', '该生需加强练习']
                        ];

                        const wb = XLSX.utils.book_new();
                        const ws = XLSX.utils.aoa_to_sheet(templateData);
                        XLSX.utils.book_append_sheet(wb, ws, '成绩模板');
                        XLSX.writeFile(wb, '成绩信息导入模板.xlsx');
                    }
                };

                const confirmImport = async () => {
                    if (!importFile.value) {
                        showToast('请先选择文件', 'danger');
                        return;
                    }

                    try {
                        const data = await readExcelFile(importFile.value);

                        if (importType.value === 'students') {
                            importStudents(data);
                        } else {
                            importGrades(data);
                        }

                        const modal = bootstrap.Modal.getInstance(document.getElementById('importModal'));
                        modal.hide();
                    } catch (error) {
                        showToast(`导入失败: ${error.message}`, 'danger');
                    }
                };

                const readExcelFile = (file) => {
                    return new Promise((resolve, reject) => {
                        const reader = new FileReader();

                        reader.onload = (e) => {
                            try {
                                const data = new Uint8Array(e.target.result);
                                const workbook = XLSX.read(data, { type: 'array' });
                                const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
                                const jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });
                                resolve(jsonData);
                            } catch (error) {
                                reject(error);
                            }
                        };

                        reader.onerror = () => {
                            reject(new Error('文件读取失败'));
                        };

                        reader.readAsArrayBuffer(file);
                    });
                };

                const importStudents = (data) => {
                    if (data.length < 2) {
                        showToast('Excel文件中没有数据', 'danger');
                        return;
                    }

                    const headers = data[0].map(h => h.trim());
                    const requiredHeaders = ['学号', '姓名'];

                    // 检查必要的表头
                    for (const reqHeader of requiredHeaders) {
                        if (!headers.includes(reqHeader)) {
                            showToast(`Excel文件缺少必要的列: ${reqHeader}`, 'danger');
                            return;
                        }
                    }

                    const newStudents = [];
                    const existingIds = students.value.map(s => s.id);

                    for (let i = 1; i < data.length; i++) {
                        const row = data[i];
                        if (row.length === 0) continue;

                        const student = {
                            id: String(row[headers.indexOf('学号')]),
                            name: String(row[headers.indexOf('姓名')]),
                            gender: headers.includes('性别') ? String(row[headers.indexOf('性别')] || '男') : '男',
                            birthday: headers.includes('出生日期') ? String(row[headers.indexOf('出生日期')]) : '',
                            phone: headers.includes('联系电话') ? String(row[headers.indexOf('联系电话')]) : '',
                            address: headers.includes('家庭住址') ? String(row[headers.indexOf('家庭住址')]) : '',
                            status: headers.includes('状态') ? String(row[headers.indexOf('状态')] || '在读') : '在读'
                        };

                        // 检查学号是否已存在
                        if (existingIds.includes(student.id)) {
                            // 更新现有学生
                            const index = students.value.findIndex(s => s.id === student.id);
                            if (index !== -1) {
                                students.value[index] = student;
                            }
                        } else {
                            // 添加新学生
                            newStudents.push(student);
                            existingIds.push(student.id);
                        }
                    }

                    students.value = [...students.value, ...newStudents];
                    saveStudents();

                    if (studentsTable.value) {
                        studentsTable.value.setData(students.value);
                    }

                    showToast(`成功导入 ${newStudents.length} 条新学生数据,更新了 ${students.value.length - newStudents.length - existingIds.length + newStudents.length} 条现有数据`);
                    logAction(`导入学生数据: ${newStudents.length} 新增, ${students.value.length - newStudents.length - existingIds.length + newStudents.length} 更新`);
                };

                const importGrades = (data) => {
                    if (data.length < 2) {
                        showToast('Excel文件中没有数据', 'danger');
                        return;
                    }

                    const headers = data[0].map(h => h.trim());
                    const requiredHeaders = ['学号', '学期'];

                    // 检查必要的表头
                    for (const reqHeader of requiredHeaders) {
                        if (!headers.includes(reqHeader)) {
                            showToast(`Excel文件缺少必要的列: ${reqHeader}`, 'danger');
                            return;
                        }
                    }

                    const newGrades = [];
                    const updatedGrades = [];

                    for (let i = 1; i < data.length; i++) {
                        const row = data[i];
                        if (row.length === 0) continue;

                        const studentId = String(row[headers.indexOf('学号')]);
                        const semester = parseInt(row[headers.indexOf('学期')]);

                        if (!studentId || isNaN(semester)) {
                            continue;
                        }

                        // 检查学生是否存在
                        if (!students.value.some(s => s.id === studentId)) {
                            continue;
                        }

                        // 创建成绩对象
                        const grade = {
                            id: generateId(),
                            studentId,
                            semester,
                            subjects: {},
                            comment: headers.includes('评语') ? String(row[headers.indexOf('评语')] || '') : ''
                        };

                        // 添加科目成绩
                        subjects.value.forEach(subject => {
                            if (headers.includes(subject)) {
                                const value = row[headers.indexOf(subject)];
                                grade.subjects[subject] = value !== undefined && value !== '' ? parseFloat(value) : null;
                            } else {
                                grade.subjects[subject] = null;
                            }
                        });

                        // 检查是否已存在该学生该学期的成绩
                        const existingIndex = grades.value.findIndex(g => g.studentId === studentId && g.semester === semester);

                        if (existingIndex !== -1) {
                            // 更新现有成绩
                            grades.value[existingIndex] = grade;
                            updatedGrades.push(grade);
                        } else {
                            // 添加新成绩
                            newGrades.push(grade);
                        }
                    }

                    grades.value = [...grades.value, ...newGrades];
                    saveGrades();

                    if (gradesTable.value) {
                        gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                    }

                    showToast(`成功导入 ${newGrades.length} 条新成绩数据,更新了 ${updatedGrades.length} 条现有数据`);
                    logAction(`导入成绩数据: ${newGrades.length} 新增, ${updatedGrades.length} 更新`);
                };

                const exportGradeExcel = () => {
                    const gradesToExport = grades.value.filter(g => g.semester === currentSemester.value);

                    if (gradesToExport.length === 0) {
                        showToast('当前学期没有成绩数据可导出', 'warning');
                        return;
                    }

                    const headers = ['学号', '姓名', '学期', ...subjects.value, '评语'];
                    const data = [headers];

                    gradesToExport.forEach(grade => {
                        const student = students.value.find(s => s.id === grade.studentId);
                        const row = [
                            grade.studentId,
                            student?.name || '未知',
                            grade.semester
                        ];

                        subjects.value.forEach(subject => {
                            row.push(grade.subjects[subject] || '');
                        });

                        row.push(grade.comment || '');
                        data.push(row);
                    });

                    const wb = XLSX.utils.book_new();
                    const ws = XLSX.utils.aoa_to_sheet(data);
                    XLSX.utils.book_append_sheet(wb, ws, '成绩数据');
                    XLSX.writeFile(wb, `第${currentSemester.value}学期成绩.xlsx`);

                    showToast('成绩导出成功');
                    logAction(`导出成绩数据: 第${currentSemester.value}学期`);
                };

                const exportData = () => {
                    const data = {
                        students: students.value,
                        grades: grades.value,
                        reportTemplates: reportTemplates.value,
                        subjects: subjects.value,
                        className: className.value,
                        teacherName: teacherName.value,
                        academicYear: academicYear.value,
                        lastBackupTime: new Date()
                    };

                    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
                    const url = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `班级成长档案备份_${formatTime(new Date()).replace(/[: ]/g, '-')}.json`;
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);

                    lastBackupTime.value = new Date();
                    saveLastBackupTime();

                    showToast('数据导出成功');
                    logAction('导出所有数据备份');
                };

                const importData = () => {
                    const input = document.createElement('input');
                    input.type = 'file';
                    input.accept = '.json';

                    input.onchange = (e) => {
                        const file = e.target.files[0];
                        if (!file) return;

                        const reader = new FileReader();

                        reader.onload = (e) => {
                            try {
                                const data = JSON.parse(e.target.result);

                                if (confirm('导入数据将覆盖当前所有数据,确定要继续吗?')) {
                                    students.value = data.students || [];
                                    grades.value = data.grades || [];
                                    reportTemplates.value = data.reportTemplates || [];
                                    subjects.value = data.subjects || ['语文', '数学', '英语'];
                                    className.value = data.className || '六年级一班';
                                    teacherName.value = data.teacherName || '张老师';
                                    academicYear.value = data.academicYear || '2022-2023';
                                    lastBackupTime.value = data.lastBackupTime ? new Date(data.lastBackupTime) : null;

                                    saveAllData();

                                    if (studentsTable.value) {
                                        studentsTable.value.setData(students.value);
                                    }

                                    if (gradesTable.value) {
                                        gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                                    }

                                    showToast('数据导入成功');
                                    logAction('导入所有数据备份');
                                }
                            } catch (error) {
                                showToast('导入失败: 文件格式不正确', 'danger');
                            }
                        };

                        reader.readAsText(file);
                    };

                    input.click();
                };

                // 报告管理方法
                const showAddTemplateModal = () => {
                    editTemplateMode.value = false;
                    Object.assign(currentTemplate, {
                        id: '',
                        name: '',
                        content: ''
                    });

                    const modal = new bootstrap.Modal(document.getElementById('addTemplateModal'));
                    modal.show();
                };

                const editTemplate = () => {
                    const template = getTemplate(selectedTemplate.value);
                    if (!template) return;

                    editTemplateMode.value = true;
                    Object.assign(currentTemplate, JSON.parse(JSON.stringify(template)));

                    const modal = new bootstrap.Modal(document.getElementById('addTemplateModal'));
                    modal.show();
                };

                const selectTemplate = (templateId) => {
                    selectedTemplate.value = templateId;

                    if (students.value.length > 0) {
                        reportStudent.value = students.value[0].id;
                    }

                    reportSemester.value = currentSemester.value;
                };

                const getTemplate = (templateId) => {
                    return reportTemplates.value.find(t => t.id === templateId);
                };

                const saveTemplate = () => {
                    if (!currentTemplate.name || !currentTemplate.content) {
                        showToast('模板名称和内容不能为空', 'danger');
                        return;
                    }

                    if (editTemplateMode.value) {
                        // 更新模板
                        const index = reportTemplates.value.findIndex(t => t.id === currentTemplate.id);
                        if (index !== -1) {
                            currentTemplate.updatedAt = new Date();
                            reportTemplates.value[index] = JSON.parse(JSON.stringify(currentTemplate));
                            showToast('模板更新成功');
                            logAction(`更新报告模板: ${currentTemplate.name}`);
                        }
                    } else {
                        // 添加新模板
                        currentTemplate.id = generateId();
                        currentTemplate.createdAt = new Date();
                        currentTemplate.updatedAt = new Date();
                        reportTemplates.value.push(JSON.parse(JSON.stringify(currentTemplate)));
                        showToast('模板添加成功');
                        logAction(`添加报告模板: ${currentTemplate.name}`);

                        // 自动选择新模板
                        selectedTemplate.value = currentTemplate.id;
                    }

                    saveReportTemplates();

                    const modal = bootstrap.Modal.getInstance(document.getElementById('addTemplateModal'));
                    modal.hide();
                };

                const insertVariable = (variable) => {
                    const textarea = document.querySelector('#addTemplateModal textarea');
                    const startPos = textarea.selectionStart;
                    const endPos = textarea.selectionEnd;
                    const variableText = `{{${variable}}}`;

                    currentTemplate.content = currentTemplate.content.substring(0, startPos) + 
                                            variableText + 
                                            currentTemplate.content.substring(endPos);

                    // 移动光标到变量后面
                    nextTick(() => {
                        textarea.selectionStart = startPos + variableText.length;
                        textarea.selectionEnd = startPos + variableText.length;
                        textarea.focus();
                    });
                };

                const generateReport = () => {
                    if (!selectedTemplate.value || !reportStudent.value) {
                        showToast('请选择模板和学生', 'danger');
                        return;
                    }

                    const template = getTemplate(selectedTemplate.value);
                    const student = students.value.find(s => s.id === reportStudent.value);
                    const grade = grades.value.find(g => g.studentId === reportStudent.value && g.semester === reportSemester.value);

                    if (!template || !student || !grade) {
                        showToast('无法生成报告,数据不完整', 'danger');
                        return;
                    }

                    // 创建PDF
                    const doc = new jspdf.jsPDF();

                    // 添加标题
                    doc.setFontSize(18);
                    doc.text(template.name, 105, 20, { align: 'center' });

                    // 添加基本信息
                    doc.setFontSize(12);
                    doc.text(`学生: ${student.name}`, 20, 40);
                    doc.text(`学号: ${student.id}`, 20, 50);
                    doc.text(`学期: 第${reportSemester.value}学期`, 20, 60);

                    // 添加成绩表格
                    const gradesData = [];
                    Object.entries(grade.subjects).forEach(([subject, score]) => {
                        gradesData.push([subject, score || '--']);
                    });

                    doc.autoTable({
                        startY: 70,
                        head: [['科目', '成绩']],
                        body: gradesData,
                        theme: 'grid',
                        headStyles: {
                            fillColor: [52, 152, 219],
                            textColor: 255
                        }
                    });

                    // 添加评语
                    if (grade.comment) {
                        doc.text('教师评语:', 20, doc.autoTable.previous.finalY + 20);
                        doc.text(grade.comment, 20, doc.autoTable.previous.finalY + 30, { maxWidth: 170 });
                    }

                    // 保存PDF
                    doc.save(`${student.name}_第${reportSemester.value}学期报告.pdf`);

                    showToast('报告生成成功');
                    logAction(`生成报告: ${student.name} 第${reportSemester.value}学期`);
                };

                const batchGenerateReports = () => {
                    if (!selectedTemplate.value) {
                        showToast('请先选择报告模板', 'danger');
                        return;
                    }

                    if (students.value.length === 0) {
                        showToast('没有学生数据', 'warning');
                        return;
                    }

                    if (confirm(`确定要为全班${students.value.length}名学生生成第${reportSemester.value}学期报告吗?`)) {
                        showToast('开始批量生成报告,请稍候...', 'info', 0);

                        // 使用setTimeout让UI有机会更新
                        setTimeout(() => {
                            const template = getTemplate(selectedTemplate.value);

                            students.value.forEach(student => {
                                const grade = grades.value.find(g => g.studentId === student.id && g.semester === reportSemester.value);
                                if (!grade) return;

                                // 创建PDF
                                const doc = new jspdf.jsPDF();

                                // 添加标题
                                doc.setFontSize(18);
                                doc.text(template.name, 105, 20, { align: 'center' });

                                // 添加基本信息
                                doc.setFontSize(12);
                                doc.text(`学生: ${student.name}`, 20, 40);
                                doc.text(`学号: ${student.id}`, 20, 50);
                                doc.text(`学期: 第${reportSemester.value}学期`, 20, 60);

                                // 添加成绩表格
                                const gradesData = [];
                                Object.entries(grade.subjects).forEach(([subject, score]) => {
                                    gradesData.push([subject, score || '--']);
                                });

                                doc.autoTable({
                                    startY: 70,
                                    head: [['科目', '成绩']],
                                    body: gradesData,
                                    theme: 'grid',
                                    headStyles: {
                                        fillColor: [52, 152, 219],
                                        textColor: 255
                                    }
                                });

                                // 添加评语
                                if (grade.comment) {
                                    doc.text('教师评语:', 20, doc.autoTable.previous.finalY + 20);
                                    doc.text(grade.comment, 20, doc.autoTable.previous.finalY + 30, { maxWidth: 170 });
                                }

                                // 保存PDF
                                doc.save(`${student.name}_第${reportSemester.value}学期报告.pdf`);
                            });

                            toast.show = false;
                            showToast(`成功为${students.value.length}名学生生成报告`);
                            logAction(`批量生成报告: ${students.value.length}名学生 第${reportSemester.value}学期`);
                        }, 100);
                    }
                };

                // 图表方法
                const renderCharts = () => {
                    renderTrendChart();
                    renderDistributionChart();
                };

                const renderAnalysisCharts = () => {
                    renderSubjectAnalysisChart();
                    renderStudentProgressChart();
                    renderCorrelationChart();
                };

                const renderTrendChart = () => {
                    const ctx = document.getElementById('trendChart');
                    if (!ctx) return;

                    // 销毁旧图表
                    if (trendChart.value) {
                        trendChart.value.destroy();
                    }

                    // 准备数据
                    const labels = Array.from({ length: 12 }, (_, i) => `第${i + 1}学期`);
                    const datasets = [];

                    if (trendSubject.value === 'all') {
                        // 显示所有科目平均分趋势
                        subjects.value.forEach(subject => {
                            const data = [];

                            for (let i = 1; i <= 12; i++) {
                                const semesterGrades = grades.value.filter(g => g.semester === i);
                                if (semesterGrades.length === 0) {
                                    data.push(null);
                                    continue;
                                }

                                let sum = 0;
                                let count = 0;

                                semesterGrades.forEach(grade => {
                                    if (grade.subjects[subject] !== null && grade.subjects[subject] !== undefined) {
                                        sum += parseFloat(grade.subjects[subject]);
                                        count++;
                                    }
                                });

                                data.push(count > 0 ? sum / count : null);
                            }

                            datasets.push({
                                label: subject,
                                data,
                                borderWidth: 2,
                                tension: 0.3,
                                fill: false
                            });
                        });
                    } else {
                        // 显示单个科目平均分趋势
                        const subject = trendSubject.value;
                        const data = [];

                        for (let i = 1; i <= 12; i++) {
                            const semesterGrades = grades.value.filter(g => g.semester === i);
                            if (semesterGrades.length === 0) {
                                data.push(null);
                                continue;
                            }

                            let sum = 0;
                            let count = 0;

                            semesterGrades.forEach(grade => {
                                if (grade.subjects[subject] !== null && grade.subjects[subject] !== undefined) {
                                    sum += parseFloat(grade.subjects[subject]);
                                    count++;
                                }
                            });

                            data.push(count > 0 ? sum / count : null);
                        }

                        datasets.push({
                            label: subject,
                            data,
                            borderWidth: 2,
                            borderColor: '#3498db',
                            backgroundColor: '#3498db',
                            tension: 0.3,
                            fill: false
                        });
                    }

                    trendChart.value = new Chart(ctx, {
                        type: 'line',
                        data: {
                            labels,
                            datasets
                        },
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            plugins: {
                                title: {
                                    display: true,
                                    text: trendSubject.value === 'all' ? '各科目平均分趋势' : `${trendSubject.value}平均分趋势`,
                                    font: {
                                        size: 16
                                    }
                                },
                                tooltip: {
                                    mode: 'index',
                                    intersect: false
                                },
                                legend: {
                                    position: 'bottom'
                                }
                            },
                            scales: {
                                y: {
                                    beginAtZero: false,
                                    min: 0,
                                    max: 100,
                                    title: {
                                        display: true,
                                        text: '分数'
                                    }
                                }
                            }
                        }
                    });
                };

                const renderDistributionChart = () => {
                    const ctx = document.getElementById('distributionChart');
                    if (!ctx) return;

                    // 销毁旧图表
                    if (distributionChart.value) {
                        distributionChart.value.destroy();
                    }

                    // 准备数据
                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    if (currentGrades.length === 0) return;

                    const segments = [
                        { min: 0, max: 60, label: '不及格' },
                        { min: 60, max: 70, label: '及格' },
                        { min: 70, max: 80, label: '中等' },
                        { min: 80, max: 90, label: '良好' },
                        { min: 90, max: 100, label: '优秀' }
                    ];

                    const data = segments.map(segment => {
                        let count = 0;

                        currentGrades.forEach(grade => {
                            Object.values(grade.subjects).forEach(score => {
                                if (score !== null && score !== undefined) {
                                    const num = parseFloat(score);
                                    if (num >= segment.min && num < segment.max) {
                                        count++;
                                    }
                                }
                            });
                        });

                        return count;
                    });

                    const labels = segments.map(s => s.label);
                    const backgroundColors = [
                        'rgba(231, 76, 60, 0.7)',
                        'rgba(241, 196, 15, 0.7)',
                        'rgba(52, 152, 219, 0.7)',
                        'rgba(46, 204, 113, 0.7)',
                        'rgba(155, 89, 182, 0.7)'
                    ];

                    distributionChart.value = new Chart(ctx, {
                        type: 'doughnut',
                        data: {
                            labels,
                            datasets: [{
                                data,
                                backgroundColor: backgroundColors,
                                borderWidth: 1
                            }]
                        },
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            plugins: {
                                title: {
                                    display: true,
                                    text: '成绩分布',
                                    font: {
                                        size: 16
                                    }
                                },
                                legend: {
                                    position: 'bottom'
                                }
                            }
                        }
                    });
                };

                const renderSubjectAnalysisChart = () => {
                    const ctx = document.getElementById('subjectAnalysisChart');
                    if (!ctx) return;

                    // 销毁旧图表
                    if (subjectAnalysisChart.value) {
                        subjectAnalysisChart.value.destroy();
                    }

                    const stats = subjectStats.value;
                    if (!stats || !stats.segmentCounts) return;

                    const labels = Object.keys(stats.segmentCounts).map(key => {
                        if (key === '0-60') return '不及格(<60)';
                        if (key === '60-70') return '及格(60-69)';
                        if (key === '70-80') return '中等(70-79)';
                        if (key === '80-90') return '良好(80-89)';
                        if (key === '90-100') return '优秀(90-99)';
                        if (key === '100') return '满分(100)';
                        return key;
                    });

                    const data = Object.values(stats.segmentCounts);
                    const backgroundColors = [
                        'rgba(231, 76, 60, 0.7)',
                        'rgba(241, 196, 15, 0.7)',
                        'rgba(52, 152, 219, 0.7)',
                        'rgba(46, 204, 113, 0.7)',
                        'rgba(155, 89, 182, 0.7)',
                        'rgba(26, 188, 156, 0.7)'
                    ];

                    subjectAnalysisChart.value = new Chart(ctx, {
                        type: 'bar',
                        data: {
                            labels,
                            datasets: [{
                                label: '人数',
                                data,
                                backgroundColor: backgroundColors,
                                borderWidth: 1
                            }]
                        },
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            plugins: {
                                title: {
                                    display: true,
                                    text: `${analysisSubject.value}成绩分布`,
                                    font: {
                                        size: 16
                                    }
                                }
                            },
                            scales: {
                                y: {
                                    beginAtZero: true,
                                    ticks: {
                                        stepSize: 1
                                    }
                                }
                            }
                        }
                    });
                };

                const renderStudentProgressChart = () => {
                    const ctx = document.getElementById('studentProgressChart');
                    if (!ctx || !progressStudent.value) return;

                    // 销毁旧图表
                    if (studentProgressChart.value) {
                        studentProgressChart.value.destroy();
                    }

                    const studentGrades = grades.value.filter(g => g.studentId === progressStudent.value);
                    if (studentGrades.length === 0) return;

                    const student = students.value.find(s => s.id === progressStudent.value);
                    const labels = [];
                    const subjectData = {};

                    // 初始化科目数据
                    subjects.value.forEach(subject => {
                        subjectData[subject] = [];
                    });

                    // 按学期排序
                    studentGrades.sort((a, b) => a.semester - b.semester);

                    // 填充数据
                    studentGrades.forEach(grade => {
                        labels.push(`第${grade.semester}学期`);

                        subjects.value.forEach(subject => {
                            subjectData[subject].push(grade.subjects[subject] || null);
                        });
                    });

                    // 创建数据集
                    const datasets = subjects.value.map(subject => ({
                        label: subject,
                        data: subjectData[subject],
                        borderWidth: 2,
                        tension: 0.3,
                        fill: false
                    }));

                    studentProgressChart.value = new Chart(ctx, {
                        type: 'line',
                        data: {
                            labels,
                            datasets
                        },
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            plugins: {
                                title: {
                                    display: true,
                                    text: `${student?.name || progressStudent.value}成绩趋势`,
                                    font: {
                                        size: 16
                                    }
                                },
                                tooltip: {
                                    mode: 'index',
                                    intersect: false
                                },
                                legend: {
                                    position: 'bottom'
                                }
                            },
                            scales: {
                                y: {
                                    beginAtZero: false,
                                    min: 0,
                                    max: 100,
                                    title: {
                                        display: true,
                                        text: '分数'
                                    }
                                }
                            }
                        }
                    });
                };

                const renderCorrelationChart = () => {
                    const ctx = document.getElementById('correlationChart');
                    if (!ctx) return;

                    // 销毁旧图表
                    if (correlationChart.value) {
                        correlationChart.value.destroy();
                    }

                    const currentGrades = grades.value.filter(g => g.semester === currentSemester.value);
                    if (currentGrades.length === 0) return;

                    // 计算相关系数矩阵
                    const matrix = [];
                    const subjectList = subjects.value;

                    // 初始化矩阵
                    for (let i = 0; i < subjectList.length; i++) {
                        matrix[i] = [];
                        for (let j = 0; j < subjectList.length; j++) {
                            matrix[i][j] = 0;
                        }
                    }

                    // 计算每对科目的相关系数
                    for (let i = 0; i < subjectList.length; i++) {
                        for (let j = i; j < subjectList.length; j++) {
                            const subject1 = subjectList[i];
                            const subject2 = subjectList[j];

                            // 收集两科目的成绩对
                            const pairs = [];

                            currentGrades.forEach(grade => {
                                const score1 = grade.subjects[subject1];
                                const score2 = grade.subjects[subject2];

                                if (score1 !== null && score1 !== undefined && 
                                    score2 !== null && score2 !== undefined) {
                                    pairs.push({
                                        x: parseFloat(score1),
                                        y: parseFloat(score2)
                                    });
                                }
                            });

                            if (pairs.length > 1) {
                                // 计算相关系数
                                const n = pairs.length;
                                let sumX = 0, sumY = 0, sumXY = 0;
                                let sumX2 = 0, sumY2 = 0;

                                pairs.forEach(pair => {
                                    sumX += pair.x;
                                    sumY += pair.y;
                                    sumXY += pair.x * pair.y;
                                    sumX2 += pair.x * pair.x;
                                    sumY2 += pair.y * pair.y;
                                });

                                const numerator = sumXY - (sumX * sumY / n);
                                const denominator = Math.sqrt((sumX2 - (sumX * sumX / n)) * (sumY2 - (sumY * sumY / n)));

                                const r = denominator !== 0 ? numerator / denominator : 0;
                                matrix[i][j] = r;
                                matrix[j][i] = r;
                            }
                        }
                    }

                    // 准备热力图数据
                    const data = {
                        labels: subjectList,
                        datasets: [{
                            data: matrix.flatMap((row, i) => row.map((value, j) => ({ x: subjectList[j], y: subjectList[i], v: value })))
                        }]
                    };

                    correlationChart.value = new Chart(ctx, {
                        type: 'matrix',
                        data,
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            plugins: {
                                title: {
                                    display: true,
                                    text: '科目成绩相关性分析',
                                    font: {
                                        size: 16
                                    }
                                },
                                tooltip: {
                                    callbacks: {
                                        title: () => '', // 禁用标题
                                        label: (context) => {
                                            const { x, y, v } = context.raw;
                                            return `${x} & ${y}: ${v.toFixed(2)}`;
                                        }
                                    }
                                },
                                legend: {
                                    display: false
                                }
                            },
                            scales: {
                                x: {
                                    type: 'category',
                                    offset: true,
                                    grid: {
                                        display: false
                                    },
                                    position: 'bottom'
                                },
                                y: {
                                    type: 'category',
                                    offset: true,
                                    grid: {
                                        display: false
                                    }
                                }
                            }
                        }
                    });
                };

                // 系统设置方法
                const addSubject = () => {
                    if (!newSubject.value.trim()) {
                        showToast('科目名称不能为空', 'danger');
                        return;
                    }

                    if (subjects.value.includes(newSubject.value.trim())) {
                        showToast('该科目已存在', 'danger');
                        return;
                    }

                    subjects.value.push(newSubject.value.trim());
                    newSubject.value = '';

                    saveSubjects();
                    showToast('科目添加成功');
                    logAction(`添加科目: ${newSubject.value}`);
                };

                const removeSubject = (subject) => {
                    if (confirm(`确定要删除科目"${subject}"吗?这将删除所有相关的成绩记录!`)) {
                        subjects.value = subjects.value.filter(s => s !== subject);

                        // 删除相关成绩
                        grades.value.forEach(grade => {
                            delete grade.subjects[subject];
                        });

                        saveSubjects();
                        saveGrades();

                        if (gradesTable.value) {
                            gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                        }

                        showToast('科目删除成功');
                        logAction(`删除科目: ${subject}`);
                    }
                };

                const saveSettings = () => {
                    localStorage.setItem('className', className.value);
                    localStorage.setItem('teacherName', teacherName.value);
                    localStorage.setItem('academicYear', academicYear.value);

                    showToast('系统设置保存成功');
                    logAction('更新系统设置');
                };

                const confirmClearData = (type) => {
                    clearDataType.value = type;
                    confirmChecked.value = false;

                    const modal = new bootstrap.Modal(document.getElementById('confirmClearModal'));
                    modal.show();
                };

                const clearData = () => {
                    if (clearDataType.value === 'students') {
                        if (confirm('确定要清空所有学生数据吗?这将同时删除所有成绩记录!')) {
                            students.value = [];
                            grades.value = [];
                            saveStudents();
                            saveGrades();

                            if (studentsTable.value) {
                                studentsTable.value.setData(students.value);
                            }

                            if (gradesTable.value) {
                                gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                            }

                            showToast('学生数据已清空');
                            logAction('清空所有学生数据');
                        }
                    } else if (clearDataType.value === 'grades') {
                        grades.value = [];
                        saveGrades();

                        if (gradesTable.value) {
                            gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                        }

                        showToast('成绩数据已清空');
                        logAction('清空所有成绩数据');
                    } else if (clearDataType.value === 'all') {
                        if (confirm('确定要清空所有数据吗?这将删除学生、成绩和所有设置!')) {
                            students.value = [];
                            grades.value = [];
                            reportTemplates.value = [];
                            subjects.value = ['语文', '数学', '英语'];
                            className.value = '六年级一班';
                            teacherName.value = '张老师';
                            academicYear.value = '2022-2023';

                            saveAllData();

                            if (studentsTable.value) {
                                studentsTable.value.setData(students.value);
                            }

                            if (gradesTable.value) {
                                gradesTable.value.setData(getGradesForSemester(currentSemester.value));
                            }

                            showToast('所有数据已清空');
                            logAction('清空所有数据');
                        }
                    }

                    const modal = bootstrap.Modal.getInstance(document.getElementById('confirmClearModal'));
                    modal.hide();
                };

                // 数据持久化方法
                const saveStudents = () => {
                    localStorage.setItem('students', JSON.stringify(students.value));
                };

                const saveGrades = () => {
                    localStorage.setItem('grades', JSON.stringify(grades.value));
                };

                const saveReportTemplates = () => {
                    localStorage.setItem('reportTemplates', JSON.stringify(reportTemplates.value));
                };

                const saveSubjects = () => {
                    localStorage.setItem('subjects', JSON.stringify(subjects.value));
                };

                const saveLogs = () => {
                    localStorage.setItem('logs', JSON.stringify(logs.value));
                };

                const saveLastBackupTime = () => {
                    localStorage.setItem('lastBackupTime', lastBackupTime.value ? lastBackupTime.value.toISOString() : '');
                };

                const saveAllData = () => {
                    saveStudents();
                    saveGrades();
                    saveReportTemplates();
                    saveSubjects();
                    saveLogs();
                    saveLastBackupTime();

                    localStorage.setItem('className', className.value);
                    localStorage.setItem('teacherName', teacherName.value);
                    localStorage.setItem('academicYear', academicYear.value);
                };

                const loadAllData = () => {
                    // 加载学生数据
                    const studentsData = localStorage.getItem('students');
                    if (studentsData) {
                        students.value = JSON.parse(studentsData);
                    }

                    // 加载成绩数据
                    const gradesData = localStorage.getItem('grades');
                    if (gradesData) {
                        grades.value = JSON.parse(gradesData);
                    }

                    // 加载报告模板
                    const templatesData = localStorage.getItem('reportTemplates');
                    if (templatesData) {
                        reportTemplates.value = JSON.parse(templatesData);
                    }

                    // 加载科目
                    const subjectsData = localStorage.getItem('subjects');
                    if (subjectsData) {
                        subjects.value = JSON.parse(subjectsData);
                    }

                    // 加载日志
                    const logsData = localStorage.getItem('logs');
                    if (logsData) {
                        logs.value = JSON.parse(logsData);
                    }

                    // 加载备份时间
                    const backupTime = localStorage.getItem('lastBackupTime');
                    if (backupTime) {
                        lastBackupTime.value = new Date(backupTime);
                    }

                    // 加载系统设置
                    const savedClassName = localStorage.getItem('className');
                    if (savedClassName) {
                        className.value = savedClassName;
                    }

                    const savedTeacherName = localStorage.getItem('teacherName');
                    if (savedTeacherName) {
                        teacherName.value = savedTeacherName;
                    }

                    const savedAcademicYear = localStorage.getItem('academicYear');
                    if (savedAcademicYear) {
                        academicYear.value = savedAcademicYear;
                    }
                };

                // 其他方法
                const viewAllLogs = () => {
                    const modal = new bootstrap.Modal(document.getElementById('allLogsModal'));
                    modal.show();
                };

                // 初始化
                onMounted(() => {
                    loadAllData();

                    // 设置默认选中的学生和模板
                    if (students.value.length > 0) {
                        progressStudent.value = students.value[0].id;
                        reportStudent.value = students.value[0].id;
                    }

                    if (reportTemplates.value.length > 0) {
                        selectedTemplate.value = reportTemplates.value[0].id;
                    }

                    // 初始化图表
                    renderCharts();

                    // 监听窗口大小变化,重新渲染图表
                    window.addEventListener('resize', () => {
                        if (currentTab.value === 'dashboard') {
                            renderCharts();
                        } else if (currentTab.value === 'analysis') {
                            renderAnalysisCharts();
                        }
                    });
                });

                // 监听相关状态变化
                watch(trendSubject, () => {
                    if (currentTab.value === 'dashboard') {
                        renderTrendChart();
                    }
                });

                watch(currentSemester, () => {
                    if (currentTab.value === 'dashboard') {
                        renderDistributionChart();
                    }
                });

                watch(analysisSubject, () => {
                    if (currentTab.value === 'analysis') {
                        renderSubjectAnalysisChart();
                    }
                });

                watch(progressStudent, () => {
                    if (currentTab.value === 'analysis') {
                        renderStudentProgressChart();
                    }
                });

                watch(currentTemplate, () => {
                    // 模板内容变化时更新预览
                }, { deep: true });

                // 暴露方法给模板
                return {
                    isSidebarCollapsed,
                    currentTab,
                    currentSemester,
                    students,
                    grades,
                    reportTemplates,
                    selectedTemplate,
                    reportStudent,
                    reportSemester,
                    subjects,
                    className,
                    teacherName,
                    academicYear,
                    logs,
                    lastBackupTime,
                    toast,
                    currentStudent,
                    currentGrade,
                    currentTemplate,
                    editStudentMode,
                    editGradeMode,
                    editTemplateMode,
                    importType,
                    importFile,
                    dragOver,
                    clearDataType,
                    confirmChecked,
                    trendSubject,
                    analysisSubject,
                    progressStudent,
                    newSubject: ref(''),
                    currentTabName,
                    studentCount,
                    averageGrade,
                    maxGrade,
                    minGrade,
                    gradeWarnings,
                    subjectStats,
                    studentProgress,
                    previewTemplateContent,
                    previewReportContent,
                    toastIcon,
                    toggleSidebar,
                    changeTab,
                    changeSemester,
                    showToast,
                    logAction,
                    formatTime,
                    showAddStudentModal,
                    editStudent,
                    saveStudent,
                    deleteStudent,
                    viewStudentDetails,
                    showAddGradeModal,
                    editGrade,
                    saveGrade,
                    deleteGrade,
                    showImportModal,
                    handleFileDrop,
                    handleFileSelect,
                    downloadTemplate,
                    confirmImport,
                    exportGradeExcel,
                    exportData,
                    importData,
                    showAddTemplateModal,
                    editTemplate,
                    selectTemplate,
                    saveTemplate,
                    insertVariable,
                    generateReport,
                    batchGenerateReports,
                    addSubject,
                    removeSubject,
                    saveSettings,
                    confirmClearData,
                    clearData,
                    viewAllLogs,
                    getTemplate
                };
            }
        }).mount('#app');

        // 注册矩阵图表类型
        Chart.register({
            id: 'matrix',
            defaults: {
                width: 400,
                height: 400
            },
            afterInit(chart) {
                const { ctx, data, chartArea: { top, bottom, left, right }, scales: { x, y } } = chart;

                // 计算每个单元格的大小
                const xAxis = x.getLabels();
                const yAxis = y.getLabels();
                const cellSize = (right - left) / xAxis.length;

                // 存储单元格位置
                chart._metasets[0]._grids = data.datasets[0].data.map(({ x: xVal, y: yVal, v }) => {
                    const xIndex = xAxis.indexOf(xVal);
                    const yIndex = yAxis.indexOf(yVal);

                    return {
                        x: left + xIndex * cellSize + cellSize / 2,
                        y: top + yIndex * cellSize + cellSize / 2,
                        width: cellSize - 2,
                        height: cellSize - 2,
                        value: v
                    };
                });
            },
            draw(chart) {
                const { ctx, chartArea: { top, bottom, left, right }, _metasets: [meta] } = chart;

                // 绘制热力图
                meta._grids.forEach(({ x, y, width, height, value }) => {
                    // 根据值计算颜色 (从蓝到红)
                    const colorValue = (value + 1) / 2; // 将范围从[-1,1]映射到[0,1]
                    const r = Math.floor(255 * colorValue);
                    const b = Math.floor(255 * (1 - colorValue));
                    const color = `rgb(${r}, 0, ${b})`;

                    ctx.fillStyle = color;
                    ctx.fillRect(x - width / 2, y - height / 2, width, height);

                    // 显示数值
                    ctx.fillStyle = 'white';
                    ctx.font = '10px Arial';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText(value.toFixed(2), x, y);
                });
            }
        });
    </script>
</body>
</html>
个人说明个人说明个人说明
上一篇

Deespeek制作单词小游戏,附上代码

下一篇

这个3D克莱因瓶互动演示!DeepSeek一键完成

你也可能喜欢

发表评论

您的电子邮件地址不会被公开。 必填项已用 * 标注

提示:点击验证后方可评论!

插入图片

最新评论

热线 热线
13888888888
QQ QQ
QQ在线咨询
微信 微信
微信
关注 关注
关注
返回顶部

微信扫一扫

微信扫一扫