200 status code is a standard successful HTTP server response. It means that the client’s request (e.g., from a browser) was successfully processed, and the server is delivering the requested data.
The user receives content without errors, and the page or application functions properly. If Code 200 is accompanied by data, the browser or program processes and displays it to the user.
GET / HTTP/1.1 Host: mz84.com Accept: */* User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>果果办公系统 - 导航主页</title> <link href="/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="/css/all.min.css"> <link rel="stylesheet" href="/css/animate.min.css"> <link rel="stylesheet" href="style.css"> <!-- 添加 Summernote 编辑器相关文件 --> <link href="/downloads/summernote-lite.min.css" rel="stylesheet"> <script src="/downloads/jquery-3.6.0.min.js"></script> <script src="/downloads/summernote-lite.min.js"></script> <script src="/downloads/summernote-zh-CN.min.js"></script> <!-- 添加编辑器相关样式 --> <style> /* 页面自定义样式略 */ .modal.fade .modal-dialog { animation: fadeInDown .3s ease-out; } .link-card { animation: fadeIn .5s ease-out; animation-fill-mode: both; } .link-card:nth-child(3n+1) { animation-delay: 0.1s; } .link-card:nth-child(3n+2) { animation-delay: 0.2s; } .link-card:nth-child(3n+3) { animation-delay: 0.3s; } .navbar .nav-link.btn { margin: 0 0.5rem; border: 1px solid rgba(0,0,0,0.1); box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .navbar .nav-link.btn:hover { background-color: #f8f9fa; border-color: rgba(0,0,0,0.2); } .navbar .dropdown-toggle::after { display: none; } .task-content { max-height: 60vh; overflow-y: auto; padding: 1rem; background-color: #f8f9fa; border-radius: 0.25rem; } /* 性能卡片样式 */ .performance-card { background: linear-gradient(135deg, #1a73e8 0%, #0d47a1 100%); border-radius: 15px; padding: 20px; box-shadow: 0 10px 20px rgba(26, 115, 232, 0.2); color: white; } /* 性能卡片标题样式 */ .performance-card h4 { color: #ffffff; font-weight: 600; } .performance-card h5 { color: rgba(255, 255, 255, 0.9) !important; font-weight: 500; margin-bottom: 1rem; } /* 性能卡片数据样式 */ .performance-card .stat-card { background: rgba(255, 255, 255, 0.1); border-radius: 10px; padding: 15px; backdrop-filter: blur(10px); transition: transform 0.3s ease; } .performance-card .stat-card:hover { transform: translateY(-5px); background: rgba(255, 255, 255, 0.15); } .performance-card .stat-label { font-size: 0.85rem; color: rgba(255, 255, 255, 0.7); margin-bottom: 5px; } .performance-card .stat-value { font-size: 1.2rem; font-weight: 600; color: #ffffff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } /* 更新时间文字样式 */ .performance-card .text-white-50 { color: rgba(255, 255, 255, 0.7) !important; } /* 排名徽章样式 */ .performance-card .rank-medal { position: relative; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; } .performance-card .crown-container { position: relative; display: inline-flex; align-items: center; justify-content: center; } .performance-card .fa-crown { color: #FFD700; font-size: 1.8rem; filter: drop-shadow(0 2px 4px rgba(255, 215, 0, 0.5)); animation: crownFloat 2s ease-in-out infinite; } .performance-card .fa-award { color: #C0C0C0; font-size: 1.6rem; filter: drop-shadow(0 2px 4px rgba(192, 192, 192, 0.5)); } .performance-card .fa-medal { color: #CD7F32; font-size: 1.6rem; filter: drop-shadow(0 2px 4px rgba(205, 127, 50, 0.5)); } .rank-number { color: #ffffff; font-size: 1.8rem; font-weight: bold; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } /* 数据卡片样式 */ .stat-card { background: rgba(255, 255, 255, 0.1); border-radius: 10px; padding: 15px; backdrop-filter: blur(10px); transition: transform 0.3s ease; } .stat-card:hover { transform: translateY(-5px); background: rgba(255, 255, 255, 0.15); } .stat-label { font-size: 0.85rem; color: rgba(255, 255, 255, 0.8); margin-bottom: 5px; } .stat-value { font-size: 1.2rem; font-weight: bold; color: white; } /* 动画效果 */ @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } } @keyframes shine { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } .performance-card::before { content: ''; position: absolute; top: 0; left: -100%; width: 200%; height: 100%; background: linear-gradient( 90deg, transparent, rgba(255, 255, 255, 0.2), transparent ); animation: shine 3s infinite; } /* 排行榜面板样式 */ .rankings-board { background: white; border-radius: 15px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); overflow: hidden; height: 400px; /* 固定高度 */ min-height: 400px; } .board-header { background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); border-bottom: 1px solid #eee; } .board-header h6 { color: #1a73e8; font-weight: 600; margin: 0; } .board-content { height: calc(100% - 41px); overflow-y: auto; } /* 标签页样式 */ .rankings-board .nav-tabs { background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); border: none; padding: 10px 10px 0; /* 减小内边距 */ } .rankings-board .nav-link { color: #6c757d; border: none; padding: 8px 15px; /* 减小内边距 */ border-radius: 10px 10px 0 0; font-weight: 500; transition: all 0.3s ease; font-size: 0.9rem; /* 减小字体 */ } .rankings-board .nav-link:hover { color: #1a73e8; } .rankings-board .nav-link.active { color: #1a73e8; background: white; font-weight: 600; } /* 排行榜内容区域 */ .rankings-board .tab-content { padding: 0; height: calc(100% - 50px); /* 减去标签页的高度 */ overflow-y: auto; } /* 排名项样式 */ .ranking-item { display: flex; align-items: center; padding: 10px 15px; /* 减小内边距 */ border-bottom: 1px solid #eee; } .ranking-item:hover { background: #f8f9fa; } .ranking-item.active { background: rgba(26, 115, 232, 0.05); border-left: 4px solid #1a73e8; } /* 排名信息布局 */ .rank-position { width: 32px; /* 减小宽度 */ height: 32px; /* 减小高度 */ font-size: 0.9rem; /* 减小字体 */ margin-right: 10px; } .rank-position i { font-size: 1rem; /* 减小图标大小 */ } .rank-position .fa-crown { color: #FFD700; filter: drop-shadow(0 2px 4px rgba(255, 215, 0, 0.3)); } .rank-position .fa-award { color: #C0C0C0; filter: drop-shadow(0 2px 4px rgba(192, 192, 192, 0.3)); } .rank-position .fa-medal { color: #CD7F32; filter: drop-shadow(0 2px 4px rgba(205, 127, 50, 0.3)); } .rank-info { flex: 1; display: flex; align-items: center; justify-content: space-between; /* 改为两端对齐 */ width: 100%; padding-right: 10px; } .rank-name { font-size: 0.9rem; font-weight: 500; color: #2c3e50; width: 80px; /* 固定名字宽度 */ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* 统计数据样式 */ .rank-stats { display: grid; grid-template-columns: repeat(3, minmax(70px, 1fr)); /* 使用网格布局,三列等宽 */ gap: 10px; text-align: right; } .stat-item { min-width: unset; /* 移除最小宽度限制 */ } .stat-label { font-size: 0.7rem; color: #6c757d; margin-bottom: 1px; } .stat-value { font-size: 0.85rem; font-weight: 600; color: #2c3e50; white-space: nowrap; /* 防止数字换行 */ } .active .stat-value { color: #1a73e8; } /* 动画效果 */ .ranking-item { animation: slideIn 0.3s ease-out; animation-fill-mode: both; } .ranking-item:nth-child(1) { animation-delay: 0.1s; } .ranking-item:nth-child(2) { animation-delay: 0.2s; } .ranking-item:nth-child(3) { animation-delay: 0.3s; } .ranking-item:nth-child(n+4) { animation-delay: 0.4s; } /* 响应式调整 */ @media (max-width: 1400px) { .rank-stats { gap: 8px; } .stat-value { font-size: 0.8rem; } } @media (max-width: 1200px) { .rank-name { width: 70px; } .rank-stats { gap: 6px; } } /* 调整列宽度 */ .col-lg-8 { width: 66.666667%; } .col-lg-4 { width: 33.333333%; } /* 在 style 标签中添加/更新分类和链接卡片样式 */ /* 分类标题样式 */ .category h2 { font-size: 1.2rem; color: #4285f4; margin-bottom: 1rem; display: flex; align-items: center; } .category h2 i { color: #4285f4; margin-right: 0.5rem; } /* 链接卡片样式 */ .link-card { display: block; padding: 1.25rem; background: #fff; border-radius: 10px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); transition: all 0.3s ease; text-decoration: none; height: 100%; border: 1px solid #e9ecef; } .link-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(66, 133, 244, 0.1); border-color: #4285f4; } .link-card .site-name { display: flex; align-items: center; font-size: 1rem; font-weight: 500; color: #4285f4; margin-bottom: 0.5rem; } .link-card .site-name i { color: #4285f4; margin-right: 0.5rem; } .link-card .site-desc { font-size: 0.875rem; color: #6c757d; line-height: 1.5; } /* 链接网格布局 */ .row.row-cols-1.row-cols-md-3 { margin: -0.75rem; } .row.row-cols-1.row-cols-md-3 > .col { padding: 0.75rem; } /* 空状态提示 */ .alert-light { background-color: #f8f9fa; border: 1px solid #e9ecef; color: #6c757d; padding: 1rem; margin-top: 0.5rem; } .alert-light i { color: #1a73e8; margin-right: 0.5rem; } /* 响应式调整 */ @media (max-width: 768px) { .category h2 { font-size: 1.1rem; } .link-card { padding: 1rem; } .link-card .site-name { font-size: 0.95rem; } .link-card .site-desc { font-size: 0.85rem; } } /* 第一名特效样式 */ .rank-position .crown-container { position: relative; display: inline-flex; align-items: center; justify-content: center; } .rank-position .fa-crown { color: #FFD700; font-size: 1.2rem; filter: drop-shadow(0 2px 4px rgba(255, 215, 0, 0.5)); animation: crownFloat 2s ease-in-out infinite; } /* 烟花效果 */ .rank-position .firework { position: absolute; width: 4px; height: 4px; border-radius: 50%; animation: firework 1.5s ease-out infinite; } .rank-position .firework:nth-child(1) { background: #FFD700; animation-delay: 0s; } .rank-position .firework:nth-child(2) { background: #FF6B6B; animation-delay: 0.2s; } .rank-position .firework:nth-child(3) { background: #4CD964; animation-delay: 0.4s; } .rank-position .firework:nth-child(4) { background: #5856D6; animation-delay: 0.6s; } @keyframes crownFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } } @keyframes firework { 0% { transform: translate(0, 0) scale(1); opacity: 1; } 50% { transform: translate(var(--x), var(--y)) scale(0.5); opacity: 0.5; } 100% { transform: translate(calc(var(--x) * 2), calc(var(--y) * 2)) scale(0); opacity: 0; } } /* 移除左侧的今日排行榜 */ .rankings-list { display: none; } /* 调整左右两栏的高度 */ .performance-card, .rankings-board { height: 400px; /* 固定高度 */ overflow: hidden; } .board-content { height: calc(100% - 41px); overflow-y: auto; } /* 调整列宽度 */ .col-lg-8 { width: 66.666667%; } .col-lg-4 { width: 33.333333%; } /* 响应式调整 */ @media (max-width: 992px) { .performance-card, .rankings-board { height: auto; margin-bottom: 1rem; } } /* 编辑器样式 */ .note-editor { margin-bottom: 1rem; border: 1px solid #ced4da !important; border-radius: 0.375rem !important; } .note-editor .note-toolbar { background-color: #f8f9fa; border-bottom: 1px solid #ced4da; padding: 0.5rem !important; border-radius: 0.375rem 0.375rem 0 0; } .note-editor .note-editing-area { background-color: #fff; } .note-editor .note-statusbar { background-color: #f8f9fa; } .note-editor .note-btn { background-color: #fff; border: 1px solid #ced4da; padding: 0.25rem 0.5rem; } .note-editor .note-btn:hover { background-color: #e9ecef; } /* 发帖模态框样式 */ .modal-post .modal-header { background: linear-gradient(135deg, #0d6efd 0%, #0a58ca 100%); color: white; border-radius: 0.375rem 0.375rem 0 0; } .modal-post .modal-title { font-weight: 600; } .modal-post .btn-close { filter: brightness(0) invert(1); } .modal-post .input-group-text { background-color: #f8f9fa; border-right: none; } .modal-post input.form-control { border-left: none; } .modal-post input.form-control:focus { box-shadow: none; border-color: #ced4da; } .modal-post .input-group:focus-within .input-group-text { border-color: #86b7fe; } </style> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <div class="container-fluid"> <a class="navbar-brand" href="/"> <i class="fas fa-home me-2"></i>果果办公系统 </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav me-auto"> </ul> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link btn btn-light text-dark px-3 rounded-pill" href="#" data-bs-toggle="modal" data-bs-target="#loginModal"> <i class="fas fa-sign-in-alt me-2"></i>登录 </a> </li> </ul> </div> </div> </nav> <div class="page-header"> <div class="container"> <h1>果果办公系统</h1> </div> </div> <div class="container py-4"> <!-- 性能卡片和排行榜部分 --> <!-- 系统公告和迷你BBS --> <div class="container-fluid px-0 mb-4"> <!-- 使用 container-fluid 和 px-0 确保宽度一致 --> <div class="row"> <!-- 系统公告 --> <div class="col-md-6"> <div class="card h-100"> <div class="card-header bg-primary text-white d-flex justify-content-between align-items-center"> <h5 class="mb-0"> <i class="fas fa-bullhorn me-2"></i>系统公告 </h5> <div> </div> </div> <div class="card-body p-0"> <div class="list-group list-group-flush announcement-list"> <div class="list-group-item"> <h6 class="mb-1"> <a href="#" class="text-decoration-none view-announcement" data-id="5" data-title="运营模块增加直通车管理" data-content="可以管理直通车数据,即将做到ai半自动化"> 运营模块增加直通车管理 </a> </h6> <small class="text-muted"> <i class="fas fa-user me-1"></i>root · <i class="fas fa-clock me-1"></i>2025-02-23 05:54 </small> </div> <div class="list-group-item"> <h6 class="mb-1"> <a href="#" class="text-decoration-none view-announcement" data-id="3" data-title="新增加天气预警系统-设置发货地和采购注意参考" data-content="<p>新增加天气预警系统-设置发货地和采购注意参考<br></p>"> 新增加天气预警系统-设置发货地和采购注意参考 </a> </h6> <small class="text-muted"> <i class="fas fa-user me-1"></i>root · <i class="fas fa-clock me-1"></i>2025-02-17 02:00 </small> </div> <div class="list-group-item text-center"> <a href="announcements_list.php" class="text-decoration-none"> <i class="fas fa-angle-double-down"></i> 查看更多公告 </a> </div> </div> </div> </div> </div> <!-- 迷你BBS --> <div class="col-md-6"> <div class="card h-100"> <div class="card-header bg-info text-white d-flex justify-content-between align-items-center"> <h5 class="mb-0"> <i class="fas fa-comments me-2"></i>迷你论坛 </h5> <div> <button class="btn btn-sm btn-light" data-bs-toggle="modal" data-bs-target="#newPostModal"> <i class="fas fa-plus"></i> 发帖 </button> </div> </div> <div class="card-body p-0"> <div class="list-group list-group-flush forum-list"> <div class="list-group-item"> <h6 class="mb-1"> <a href="#" class="text-decoration-none view-post " data-id="2" data-title="有BUG留言" data-content="有BUG此贴留言"> <i class="fas fa-thumbtack text-warning me-1"></i> 有BUG留言 </a> <span class="badge bg-info float-end">0 回复</span> </h6> <small class="text-muted"> <i class="fas fa-user me-1"></i>root · <i class="fas fa-clock me-1"></i>2025-02-16 15:29 </small> </div> <div class="list-group-item text-center"> <a href="forum_list.php" class="text-decoration-none"> <i class="fas fa-angle-double-down"></i> 查看更多帖子 </a> </div> </div> </div> </div> </div> </div> </div> <!-- 模块列表部分 --> </div> <footer class="footer mt-auto py-3 bg-light"> <div class="container"> <div class="row align-items-center"> <div class="col-md-6 text-center text-md-start"> <span class="text-muted"> <i class="fas fa-code"></i> 果果办公系统 © 2025 </span> </div> <div class="col-md-6 text-center text-md-end"> <div class="footer-links"> <a href="#" class="text-muted text-decoration-none me-3"> <i class="fas fa-shield-alt"></i> 隐私政策 </a> <a href="#" class="text-muted text-decoration-none me-3"> <i class="fas fa-file-contract"></i> 使用条款 </a> <a href="#" class="text-muted text-decoration-none"> <i class="fas fa-question-circle"></i> 帮助中心 </a> </div> </div> </div> </div> </footer> <!-- 登录模态框 --> <div class="modal fade" id="loginModal" tabindex="-1"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content border-0 shadow"> <div class="modal-header border-0 bg-primary text-white"> <h5 class="modal-title"><i class="fas fa-user-circle"></i> 用户登录</h5> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> </div> <div class="modal-body p-4"> <div id="loginError" class="alert alert-danger d-none"></div> <form id="loginForm" class="needs-validation" novalidate> <div class="mb-3"> <div class="input-group"> <span class="input-group-text"><i class="fas fa-user"></i></span> <input type="text" class="form-control" name="username" placeholder="请输入用户名" required> </div> </div> <div class="mb-4"> <div class="input-group"> <span class="input-group-text"><i class="fas fa-lock"></i></span> <input type="password" class="form-control" name="password" placeholder="请输入密码" required> </div> </div> <button type="submit" class="btn btn-primary w-100 mb-3"> <i class="fas fa-sign-in-alt me-2"></i> 登录 </button> </form> </div> </div> </div> </div> <!-- 显示设置模态框 --> <div class="modal fade" id="settingsModal" tabindex="-1"> <div class="modal-dialog modal-dialog-centered modal-lg"> <div class="modal-content border-0 shadow"> <div class="modal-header bg-primary text-white border-0"> <h5 class="modal-title"> <i class="fas fa-columns me-2"></i>显示设置 </h5> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <div class="alert alert-info mb-3"> <i class="fas fa-info-circle me-2"></i> 拖动模块可以调整顺序,使用复选框控制显示或隐藏(只展示您有权限的模块和链接) </div> <form id="displaySettingsForm"> <div class="list-group" id="sortableCategories"> </div> </form> </div> <div class="modal-footer border-0"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> <i class="fas fa-times me-2"></i>取消 </button> <button type="button" class="btn btn-primary" id="saveSettings"> <i class="fas fa-save me-2"></i>保存设置 </button> </div> </div> </div> </div> <!-- Toast 提示 --> <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11"> <div id="settingsToast" class="toast align-items-center text-white bg-success border-0" role="alert"> <div class="d-flex"> <div class="toast-body"> <i class="fas fa-check-circle me-2"></i>设置已保存 </div> <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button> </div> </div> </div> <!-- 任务查看模态框 --> <div class="modal fade" id="viewTaskModal" tabindex="-1"> <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"></button> </div> <div class="modal-body"> <div class="task-content" style="white-space: pre-wrap;"></div> </div> </div> </div> </div> <!-- 系统公告查看模态框 --> <div class="modal fade" id="viewAnnouncementModal" tabindex="-1"> <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"></button> </div> <div class="modal-body"> <div class="announcement-content" style="white-space: pre-wrap;"></div> </div> </div> </div> </div> <!-- 发布公告模态框 --> <div class="modal fade" id="newAnnouncementModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">发布系统公告</h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <form id="announcementForm"> <div class="mb-3"> <label class="form-label">标题</label> <input type="text" class="form-control" name="title" required> </div> <div class="mb-3"> <label class="form-label">内容</label> <textarea class="form-control" name="content" rows="5" required></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" onclick="submitAnnouncement()">发布</button> </div> </div> </div> </div> <!-- 帖子查看/回复模态框 --> <div class="modal fade" id="viewPostModal" tabindex="-1"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header bg-primary text-white"> <h5 class="modal-title"></h5> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <div class="post-content"></div> <hr> <div class="replies-list"></div> <form id="replyForm" class="mt-4"> <input type="hidden" name="post_id"> <div class="mb-3"> <label class="form-label fw-bold"> <i class="fas fa-reply me-2"></i>发表回复 </label> <textarea id="replyEditor" name="content" required></textarea> </div> <div class="text-end"> <button type="button" class="btn btn-secondary me-2" data-bs-dismiss="modal"> <i class="fas fa-times me-2"></i>取消 </button> <button type="submit" class="btn btn-primary"> <i class="fas fa-paper-plane me-2"></i>提交回复 </button> </div> </form> </div> </div> </div> </div> <!-- 发帖模态框 --> <div class="modal fade modal-post" id="newPostModal" tabindex="-1"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title"> <i class="fas fa-edit me-2"></i>发布新帖 </h5> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <form id="postForm"> <div class="mb-3"> <label class="form-label fw-bold"> <i class="fas fa-heading me-2"></i>标题 </label> <div class="input-group"> <span class="input-group-text"> <i class="fas fa-pen"></i> </span> <input type="text" class="form-control" name="title" required placeholder="请输入帖子标题"> </div> </div> <div class="mb-3"> <label class="form-label fw-bold"> <i class="fas fa-file-alt me-2"></i>内容 </label> <textarea id="postEditor" name="content" required></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> <i class="fas fa-times me-2"></i>取消 </button> <button type="button" class="btn btn-primary" onclick="submitPost()"> <i class="fas fa-paper-plane me-2"></i>发布 </button> </div> </div> </div> </div> <script src="/js/bootstrap.bundle.min.js"></script> <script src="/js/Sortable.min.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { // 如果用户未登录,自动显示登录弹窗 const loginModal = new bootstrap.Modal(document.getElementById('loginModal')); setTimeout(() => loginModal.show(), 800); // 登录表单提交 const loginForm = document.getElementById('loginForm'); const loginButton = loginForm.querySelector('button[type="submit"]'); const errorDiv = document.getElementById('loginError'); loginForm.addEventListener('submit', async function(e) { e.preventDefault(); loginButton.disabled = true; loginButton.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>登录中...'; errorDiv.classList.add('d-none'); try { const formData = new URLSearchParams(new FormData(this)); const response = await fetch('login.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' }, body: formData.toString() }); if (!response.ok) { throw new Error('网络请求失败'); } const data = await response.json(); if (data.error) { errorDiv.textContent = data.error; errorDiv.classList.remove('d-none'); // 动画 errorDiv.classList.add('animate__animated', 'animate__shakeX'); errorDiv.addEventListener('animationend', () => { errorDiv.classList.remove('animate__animated', 'animate__shakeX'); }); } else { // 登录成功,刷新页面 document.body.style.opacity = '0'; document.body.style.transition = 'opacity 0.3s'; setTimeout(() => location.reload(), 300); } } catch (error) { console.error('登录失败:', error); errorDiv.textContent = '登录请求失败,请重试'; errorDiv.classList.remove('d-none'); } finally { loginButton.disabled = false; loginButton.innerHTML = '<i class="fas fa-sign-in-alt me-2"></i> 登录'; } }); // 拖拽排序 new Sortable(document.getElementById('sortableCategories'), { handle: '.handle', animation: 150 }); // 展开/收起链接容器 document.querySelectorAll('.toggle-links').forEach(button => { button.addEventListener('click', function() { const icon = this.querySelector('i'); const container = this.closest('.list-group-item').querySelector('.links-container'); if (container.style.display === 'none') { container.style.display = 'block'; icon.classList.replace('fa-chevron-down', 'fa-chevron-up'); } else { container.style.display = 'none'; icon.classList.replace('fa-chevron-up', 'fa-chevron-down'); } }); }); // 模块复选框联动 - 选中模块则选中所有链接 document.querySelectorAll('.category-toggle').forEach(catCheckbox => { catCheckbox.addEventListener('change', function() { const categoryId = this.dataset.categoryId; const linkCheckboxes = document.querySelectorAll(`.link-toggle[data-category-id="${categoryId}"]`); linkCheckboxes.forEach(l => { l.checked = this.checked; }); }); }); // 保存设置 document.getElementById('saveSettings').addEventListener('click', async function() { const button = this; button.disabled = true; const originalText = button.innerHTML; button.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>保存中...'; // 收集分类、排序、可见性 const categoryItems = Array.from(document.querySelectorAll('#sortableCategories .list-group-item')); const categoriesData = categoryItems.map((item, index) => { const catId = item.dataset.id; const catChecked = item.querySelector('.category-toggle').checked; const links = Array.from(item.querySelectorAll('.link-toggle')).map(linkChk => ({ id: linkChk.value, visible: linkChk.checked })); return { id: catId, visible: catChecked, order: index, links }; }); try { const response = await fetch('save_settings.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ categories: categoriesData }) }); if (!response.ok) { throw new Error(`HTTP Error: ${response.status}`); } const data = await response.json(); if (data.success) { // 显示 Toast const toastEl = document.getElementById('settingsToast'); const toast = new bootstrap.Toast(toastEl); toast.show(); // 1秒后刷新 setTimeout(() => location.reload(), 1000); } else { throw new Error(data.error || '保存失败'); } } catch (error) { alert('保存设置失败:' + error.message); console.error(error); } finally { button.disabled = false; button.innerHTML = originalText; } }); // 查看任务详情(示例) document.querySelectorAll('.view-task').forEach(link => { link.addEventListener('click', async function(e) { e.preventDefault(); const modal = document.getElementById('viewTaskModal'); modal.querySelector('.modal-title').textContent = this.dataset.title; const contentDiv = modal.querySelector('.task-content'); contentDiv.textContent = this.dataset.content; new bootstrap.Modal(modal).show(); // 如果是普通任务且未读,标记为已读 if (!this.dataset.recurring && this.dataset.status === 'unread') { try { await fetch('read_task.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: this.dataset.id }) }); // 成功后可以更新状态,如移除未读标记等 } catch (err) { console.error('标记已读失败:', err); } } }); }); // 查看公告 document.querySelectorAll('.view-announcement').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const modal = document.getElementById('viewAnnouncementModal'); modal.querySelector('.modal-title').textContent = this.dataset.title; modal.querySelector('.announcement-content').textContent = this.dataset.content; new bootstrap.Modal(modal).show(); }); }); // 查看帖子 document.querySelectorAll('.view-post').forEach(link => { link.addEventListener('click', async function(e) { e.preventDefault(); const modal = document.getElementById('viewPostModal'); try { // 先显示模态框 const bsModal = new bootstrap.Modal(modal); bsModal.show(); // 设置标题和内容 modal.querySelector('.modal-title').textContent = this.dataset.title; modal.querySelector('.post-content').innerHTML = this.dataset.content; modal.querySelector('[name="post_id"]').value = this.dataset.id; // 初始化回复编辑器 if ($('#replyEditor').data('summernote')) { $('#replyEditor').summernote('destroy'); } $('#replyEditor').summernote({ lang: 'zh-CN', height: 150, placeholder: '请输入回复内容...', toolbar: [ ['font', ['bold', 'underline', 'clear']], ['color', ['color']], ['para', ['ul', 'ol']], ['insert', ['link', 'picture']], ['view', ['fullscreen']] ], callbacks: { onImageUpload: function(files) { for (let file of files) { uploadImage(file, this); } } } }); // 加载回复 const response = await fetch(`get_replies.php?post_id=${this.dataset.id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const replies = await response.json(); if (Array.isArray(replies)) { const repliesList = modal.querySelector('.replies-list'); repliesList.innerHTML = replies.map(reply => ` <div class="reply-item mb-3"> <div class="d-flex justify-content-between"> <div> <strong class="text-primary"> <i class="fas fa-user-circle me-1"></i>${reply.username} </strong> <small class="text-muted ms-2"> <i class="fas fa-clock me-1"></i>${reply.created_at} </small> </div> </div> <div class="reply-content mt-2">${reply.content}</div> </div> `).join(''); // 处理所有图片 repliesList.querySelectorAll('img').forEach(img => { img.style.maxWidth = '100%'; img.classList.add('img-fluid'); // 压缩图片 if (!img.src.includes('?')) { img.src = img.src + '?w=800'; } }); } else { throw new Error('回复数据格式错误'); } } catch (error) { console.error('加载回复失败:', error); showToast('error', '加载回复失败: ' + error.message); } }); }); // 提交回复 document.getElementById('replyForm').addEventListener('submit', async function(e) { e.preventDefault(); const submitBtn = this.querySelector('button[type="submit"]'); const originalHtml = submitBtn.innerHTML; try { submitBtn.disabled = true; submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>提交中...'; const formData = new FormData(this); // 获取编辑器内容 formData.set('content', $('#replyEditor').summernote('code')); const response = await fetch('submit_reply.php', { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { showToast('success', '回复成功!'); // 清空编辑器 $('#replyEditor').summernote('reset'); // 重新加载回复列表 await loadReplies(formData.get('post_id')); } else { throw new Error(data.error || '回复失败'); } } catch (error) { console.error('提交回复失败:', error); showToast('error', error.message); } finally { submitBtn.disabled = false; submitBtn.innerHTML = originalHtml; } }); // 加载回复函数 async function loadReplies(postId) { try { const response = await fetch(`get_replies.php?post_id=${postId}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const replies = await response.json(); if (Array.isArray(replies)) { const repliesList = document.querySelector('.replies-list'); repliesList.innerHTML = replies.map(reply => ` <div class="reply-item mb-3"> <div class="d-flex justify-content-between"> <div> <strong class="text-primary"> <i class="fas fa-user-circle me-1"></i>${reply.username} </strong> <small class="text-muted ms-2"> <i class="fas fa-clock me-1"></i>${reply.created_at} </small> </div> </div> <div class="reply-content mt-2">${reply.content}</div> </div> `).join(''); // 处理所有图片 repliesList.querySelectorAll('img').forEach(img => { img.style.maxWidth = '100%'; img.classList.add('img-fluid'); if (!img.src.includes('?')) { img.src = img.src + '?w=800'; } }); } else { throw new Error('回复数据格式错误'); } } catch (error) { console.error('加载回复失败:', error); showToast('error', '加载回复失败: ' + error.message); } } }); // 全局完成任务函数 async function completeTask(taskId) { if (!confirm('确定要完成这个任务吗?')) return; const button = event.target.closest('button'); if (!button) return; const originalHtml = button.innerHTML; button.disabled = true; button.innerHTML = '<span class="spinner-border spinner-border-sm"></span>'; try { const response = await fetch('complete_task.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: taskId }) }); if (!response.ok) { throw new Error(`操作失败: ${response.status}`); } const data = await response.json(); if (data.success) { // 小提示 const toast = document.createElement('div'); toast.className = 'position-fixed top-50 start-50 translate-middle bg-success text-white p-3 rounded'; toast.style.zIndex = '9999'; toast.innerHTML = ` <div class="d-flex align-items-center"> <i class="fas fa-check-circle me-2"></i> <span>已完成</span> </div>`; document.body.appendChild(toast); setTimeout(() => location.reload(), 1000); } else { throw new Error(data.error || '操作失败'); } } catch (error) { console.error('操作失败:', error); alert('操作失败:' + error.message); } finally { button.disabled = false; button.innerHTML = originalHtml; } } // 提交公告 async function submitAnnouncement() { const form = document.getElementById('announcementForm'); const formData = new FormData(form); try { const response = await fetch('submit_announcement.php', { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { location.reload(); } else { alert(data.error || '发布失败'); } } catch (error) { console.error('发布公告失败:', error); alert('发布公告失败'); } } // 在 DOMContentLoaded 事件中初始化编辑器 document.addEventListener('DOMContentLoaded', function() { // 初始化发帖编辑器 $('#postEditor').summernote({ lang: 'zh-CN', height: 300, placeholder: '请输入帖子内容...', toolbar: [ ['style', ['style']], ['font', ['bold', 'underline', 'clear']], ['color', ['color']], ['para', ['ul', 'ol', 'paragraph']], ['table', ['table']], ['insert', ['link', 'picture', 'video']], ['view', ['fullscreen', 'codeview']] ], callbacks: { onImageUpload: function(files) { for (let file of files) { uploadImage(file, this); } } } }); }); // 上传图片函数 async function uploadImage(file, editor) { const formData = new FormData(); formData.append('image', file); try { const response = await fetch('upload_image.php', { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { $(editor).summernote('insertImage', data.url); } else { showToast('error', '上传图片失败:' + data.error); } } catch (error) { console.error('上传图片失败:', error); showToast('error', '上传图片失败'); } } // 提交帖子函数 async function submitPost() { const form = document.getElementById('postForm'); const submitBtn = document.querySelector('#newPostModal .btn-primary'); const originalHtml = submitBtn.innerHTML; if (!form.checkValidity()) { form.reportValidity(); return; } try { submitBtn.disabled = true; submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>发布中...'; const formData = new FormData(form); formData.set('content', $('#postEditor').summernote('code')); const response = await fetch('submit_post.php', { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { // 显示成功提示 showToast('success', '发布成功!'); // 清空表单 form.reset(); $('#postEditor').summernote('reset'); // 关闭模态框并刷新论坛区域 setTimeout(async () => { // 关闭模态框 bootstrap.Modal.getInstance(document.getElementById('newPostModal')).hide(); // 刷新论坛列表 try { const response = await fetch('get_forum_posts.php'); const posts = await response.json(); updateForumList(posts); } catch (error) { console.error('刷新帖子列表失败:', error); location.reload(); // 如果AJAX刷新失败,则整页刷新 } }, 1000); } else { throw new Error(data.error || '发布失败'); } } catch (error) { console.error('发布帖子失败:', error); showToast('error', error.message); } finally { submitBtn.disabled = false; submitBtn.innerHTML = originalHtml; } } // 更新论坛列表函数 function updateForumList(posts) { const forumList = document.querySelector('.forum-list'); if (!forumList) return; forumList.innerHTML = posts.length ? posts.map(post => ` <div class="list-group-item"> <h6 class="mb-1"> <a href="#" class="text-decoration-none view-post ${post.is_important ? 'text-danger' : ''}" data-id="${post.id}" data-title="${post.title}" data-content="${post.content}"> ${post.is_sticky ? '<i class="fas fa-thumbtack text-warning me-1"></i>' : ''} ${post.title} </a> <span class="badge bg-info float-end">${post.reply_count} 回复</span> </h6> <small class="text-muted"> <i class="fas fa-user me-1"></i>${post.username} · <i class="fas fa-clock me-1"></i>${post.created_at} </small> </div> `).join('') : ` <div class="list-group-item text-center text-muted py-4"> <i class="fas fa-info-circle me-2"></i>暂无帖子 </div> `; // 重新绑定查看帖子事件 document.querySelectorAll('.view-post').forEach(link => { link.addEventListener('click', viewPost); }); } </script> </body> </html>