CF _worker搭建 WS01 Note-20251019

CF _worker搭建 WS01 Note-20251019

wszx01
2025-10-19 / 0 评论 / 1 阅读

CF _worker搭建 WS01 Note,可设置私人日记或公开分享

变量设置:
1、帐号:USERNAME,默认:9527a
2、密码:PASSWORD,默认:9527abc
3、KV空间邦定:WS01_NOTE_KV

// WS01 Note - Cloudflare Workers + KV 日记本应用
// 作者: WS01
// 功能: 基于Cloudflare Workers和KV数据库的简单日记本

export default {
    async fetch(request, env, ctx) {
      const url = new URL(request.url);
      const path = url.pathname;
  
      // 处理CORS
      const corsHeaders = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
      };
  
      if (request.method === 'OPTIONS') {
        return new Response(null, { status: 200, headers: corsHeaders });
      }
  
      try {
        // 路由处理
        if (path === '/' || path === '/login') {
          return new Response(getLoginPage(), {
            headers: { 'Content-Type': 'text/html; charset=utf-8', ...corsHeaders }
          });
        }
  
        if (path === '/diary') {
          return new Response(getDiaryPage(), {
            headers: { 'Content-Type': 'text/html; charset=utf-8', ...corsHeaders }
          });
        }
  
        // 查看具体日记页面
        if (path.startsWith('/diary/') && path.split('/').length === 3) {
          const diaryId = path.split('/')[2];
          return new Response(getDiaryDetailPage(diaryId), {
            headers: { 'Content-Type': 'text/html; charset=utf-8', ...corsHeaders }
          });
        }

        // 分享日记目录页面路由
        if (path === '/share') {
          return new Response(getShareIndexPage(), {
            headers: { 'Content-Type': 'text/html; charset=utf-8', ...corsHeaders }
          });
        }

        // 分享页面路由
        if (path.startsWith('/share/') && path.split('/').length === 3) {
          const shareId = path.split('/')[2];
          return new Response(getSharePage(shareId), {
            headers: { 'Content-Type': 'text/html; charset=utf-8', ...corsHeaders }
          });
        }
  
        if (path === '/api/auth') {
          return handleAuth(request, env, corsHeaders);
        }
  
        if (path === '/api/diary') {
          return handleDiaryAPI(request, env, corsHeaders);
        }

        // 添加分享相关API路由
        if (path === '/api/diary/share' && (request.method === 'POST' || request.method === 'PUT')) {
          return handleShareDiary(request, env, corsHeaders);
        }
        
        // 获取分享日记API路由
        if (path.startsWith('/api/share/') && path.split('/').length === 4) {
          const shareId = path.split('/')[3];
          return handleGetSharedDiary(shareId, env, corsHeaders);
        }
        
        // 获取所有分享日记API路由
        if (path === '/api/shares' && request.method === 'GET') {
          return handleGetAllShares(request, env, corsHeaders);
        }
        
        // 获取用户分享日记列表API路由
        if (path === '/api/diary/shares' && request.method === 'GET') {
          return handleGetUserShares(request, env, corsHeaders);
        }
        
        // 删除分享日记API路由
        if (path === '/api/diary/share' && request.method === 'DELETE') {
          return handleDeleteShare(request, env, corsHeaders);
        }

        // 添加备份相关API路由
        if (path === '/api/diary/backup' && request.method === 'POST') {
          return handleCreateBackup(request, env, corsHeaders);
        }
        
        if (path === '/api/diary/backups' && request.method === 'GET') {
          return handleGetBackups(request, env, corsHeaders);
        }
        
        if (path === '/api/diary/restore' && request.method === 'POST') {
          return handleRestoreBackup(request, env, corsHeaders);
        }
        
        if (path === '/api/diary/backup' && request.method === 'DELETE') {
          return handleDeleteBackup(request, env, corsHeaders);
        }
  
        // 404处理
        return new Response('页面未找到', { 
          status: 404, 
          headers: { 'Content-Type': 'text/plain; charset=utf-8', ...corsHeaders }
        });
  
      } catch (error) {
        console.error('Worker错误:', error);
        return new Response('服务器内部错误', { 
          status: 500, 
          headers: { 'Content-Type': 'text/plain; charset=utf-8', ...corsHeaders }
        });
      }
    }
  };
  
  // 登录页面
  function getLoginPage() {
    return `
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WS01 Note - 登录</title>
      <style>
          * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
          }
          
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
              min-height: 100vh;
              display: flex;
              align-items: center;
              justify-content: center;
          }
          
          .login-container {
              background: white;
              padding: 1.5rem;
              border-radius: 8px;
              box-shadow: 0 10px 25px rgba(0,0,0,0.08);
              width: 100%;
              max-width: 360px;
          }
          
          .logo {
              text-align: center;
              margin-bottom: 1.5rem;
          }
          
          .logo h1 {
              color: #333;
              font-size: 1.6rem;
              font-weight: 400;
          }
          
          .logo p {
              color: #666;
              margin-top: 0.3rem;
              font-size: 0.9rem;
          }
          
          .form-group {
              margin-bottom: 1.2rem;
          }
          
          .form-group label {
              display: block;
              margin-bottom: 0.4rem;
              color: #333;
              font-weight: 500;
              font-size: 0.9rem;
          }
          
          .form-group input {
              width: 100%;
              padding: 0.6rem;
              border: 1px solid #e1e5e9;
              border-radius: 6px;
              font-size: 0.9rem;
              transition: border-color 0.3s;
          }
          
          .form-group input:focus {
              outline: none;
              border-color: #667eea;
          }
          
          .login-btn {
              width: 100%;
              padding: 0.6rem;
              background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
              color: white;
              border: none;
              border-radius: 6px;
              font-size: 0.9rem;
              font-weight: 500;
              cursor: pointer;
              transition: transform 0.2s;
          }
          
          .login-btn:hover {
              transform: translateY(-2px);
          }
          
          .error-message {
              color: #e74c3c;
              text-align: center;
              margin-top: 1rem;
              display: none;
          }
      </style>
  </head>
  <body>
      <div class="login-container">
          <div class="logo">
              <h1>WS01 Note</h1>
              <p>您的私人日记本</p>
          </div>
          
          <form id="loginForm">
              <div class="form-group">
                  <label for="username">用户名</label>
                  <input type="text" id="username" name="username" required>
              </div>
              
              <div class="form-group">
                  <label for="password">密码</label>
                  <input type="password" id="password" name="password" required>
              </div>
              
              <button type="submit" class="login-btn">登录</button>
          </form>
          
          <div id="errorMessage" class="error-message"></div>
      </div>
  
      <script>
          document.getElementById('loginForm').addEventListener('submit', async (e) => {
              e.preventDefault();
              
              const username = document.getElementById('username').value;
              const password = document.getElementById('password').value;
              const errorDiv = document.getElementById('errorMessage');
              
              try {
                  const response = await fetch('/api/auth', {
                      method: 'POST',
                      headers: {
                          'Content-Type': 'application/json',
                      },
                      body: JSON.stringify({ username, password })
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      localStorage.setItem('ws01_token', result.token);
                      window.location.href = '/diary';
                  } else {
                      errorDiv.textContent = result.message || '登录失败';
                      errorDiv.style.display = 'block';
                  }
              } catch (error) {
                  errorDiv.textContent = '网络错误,请重试';
                  errorDiv.style.display = 'block';
              }
          });
      </script>
  </body>
  </html>`;
  }
  
  // 日记页面
  function getDiaryPage() {
    return `
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WS01 Note - 我的日记</title>
      <style>
          * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
          }
          
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: #f8f9fa;
              min-height: 100vh;
          }
  
  .sites {
  width:1000px;
  background:#F2F2F2;
  border:1px solid rgba(0,0,0,.06);
  margin:10px auto;
  padding:0px;
  color: white;
  border-radius: 6px;
  }
  
  .sites01 {
  width:1280px;
  background:;
  border:2px solid auto;
  margin:15px auto;
  padding:0px;
  }
  
  .sites dl {
  height:36px;
  line-height:36px;
  display:block;
  margin:0;
  }
  
  .sites dl.alt {
  background:#c5dff6;
  border-top:1px solid #ffffff;
  border-bottom:1px solid #ffffff;
  }
  
  .sites dl.alt2 {
  background:#dcecfa;
  border-top:1px solid #ffffff;
  border-bottom:1px solid #ffffff;
  }
  
  .sites dt,.sites dd {
  text-align:center;
  display:block;
  float:left;
  }
  
  .sites dt {
  width:60px;
  }
  
  .sites dd {
  width:90px;
  margin:0;
  }
  
          
          .header {
              background: #D4D4D4;
              padding: 0.8rem 1.5rem;
              box-shadow: 0 1px 6px rgba(0,0,0,0.08);
              display: flex;
              justify-content: center;
              align-items: center;
              position: relative;
          }
          
          .logo {
              font-size: 1.5rem;
              font-weight: 400;
              color: #333;
          }
          
          .logout-btn {
              background: #e74c3c;
              color: white;
              border: none;
              width: 40px;
              height: 40px;
              border-radius: 50%;
              cursor: pointer;
              font-size: 1.2rem;
              position: absolute;
              right: 2.6rem;
              display: flex;
              align-items: center;
              justify-content: center;
              transition: transform 0.2s;
          }
          
          .logout-btn:hover {
              background: #c0392b;
              transform: scale(1.1);
          }
          
          .container {
              max-width: 960px;
              margin: 1.5rem auto;
              padding: 0 1.5rem;
              display: flex;
              gap: 1.5rem;
          }
          
          .main-content {
              flex: 1;
              min-width: 0;
          }
          
          .sidebar {
              width: 300px;
              flex-shrink: 0;
          }
          
          /* 搜索框样式 */
          .search-section {
              margin-bottom: 1rem;
          }
          
          .search-container {
              position: relative;
              background: white;
              border-radius: 8px;
              box-shadow: 0 2px 12px rgba(0,0,0,0.08);
              overflow: hidden;
          }
          
          .search-input {
              width: 100%;
              padding: 0.8rem 2.5rem 0.8rem 0.8rem;
              border: none;
              border-radius: 8px;
              font-size: 0.9rem;
              background: white;
              transition: all 0.3s ease;
          }
          
          .search-input:focus {
              outline: none;
              box-shadow: 0 0 0 2px #667eea;
          }
          
          .search-input::placeholder {
              color: #999;
              font-size: 0.85rem;
          }
          
          .clear-search-btn {
              position: absolute;
              right: 0.5rem;
              top: 50%;
              transform: translateY(-50%);
              background: none;
              border: none;
              color: #999;
              font-size: 1.2rem;
              cursor: pointer;
              padding: 0.2rem;
              border-radius: 50%;
              width: 24px;
              height: 24px;
              display: flex;
              align-items: center;
              justify-content: center;
              transition: all 0.2s ease;
          }
          
          .clear-search-btn:hover {
              background: #f0f0f0;
              color: #666;
          }
          
          .clear-search-btn.hidden {
              display: none;
          }
          
          .diary-form {
              background: white;
              padding: 1.5rem;
              border-radius: 8px;
              box-shadow: 0 2px 12px rgba(0,0,0,0.08);
          }
          
          .diary-form-header {
              display: flex;
              justify-content: space-between;
              align-items: center;
              margin-bottom: 1.2rem;
          }
          
          .diary-form-title {
              color: #333;
              margin: 0;
              font-size: 1.3rem;
          }
          
          .current-time {
              color: #666;
              font-size: 0.8rem;
          }
          
          /* 添加保存按钮图标样式 */
          .save-btn-icon {
              background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
              color: white;
              border: none;
              width: 32px;
              height: 32px;
              border-radius: 50%;
              cursor: pointer;
              font-size: 1rem;
              display: flex;
              align-items: center;
              justify-content: center;
              box-shadow: 0 2px 8px rgba(0,0,0,0.15);
              transition: transform 0.2s;
          }
          
          .save-btn-icon:hover {
              transform: scale(1.1);
          }
          
          /* 添加分享按钮样式 */
          .share-btn-icon {
              background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
              color: white;
              border: none;
              width: 32px;
              height: 32px;
              border-radius: 50%;
              cursor: pointer;
              font-size: 1rem;
              display: flex;
              align-items: center;
              justify-content: center;
              box-shadow: 0 2px 8px rgba(0,0,0,0.15);
              transition: transform 0.2s;
          }
          
          .share-btn-icon:hover {
              transform: scale(1.1);
          }

          /* 添加分享按钮样式 */
          .share01-btn-icon {
              background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
              color: white;
              border: none;
              width: 40px;
              height: 40px;
              border-radius: 50%;
              cursor: pointer;
              font-size: 1.2rem;
              display: flex;
              align-items: center;
              justify-content: center;
              box-shadow: 0 2px 8px rgba(0,0,0,0.15);
              transition: transform 0.2s;
              text-decoration: none;
          }
          
          .share01-btn-icon:hover {
              transform: scale(1.1);
          }

          
        .header-with-button {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .header-controls {
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }
        
        .font-size-select {
            padding: 0.3rem 0.5rem;
            border: 1px solid #e1e5e9;
            border-radius: 4px;
            font-size: 0.8rem;
            background: white;
            cursor: pointer;
            transition: border-color 0.3s;
        }
        
        .font-size-select:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .font-size-select:hover {
            border-color: #667eea;
        }
          
          .form-group {
              margin-bottom: 1.2rem;
          }
          
          .form-group label {
              display: block;
              margin-bottom: 0.4rem;
              color: #333;
              font-weight: 500;
              font-size: 0.9rem;
          }
          
          .form-group input,
          .form-group textarea {
              width: 100%;
              padding: 0.6rem;
              border: 1px solid #e1e5e9;
              border-radius: 6px;
              font-size: 0.9rem;
              font-family: inherit;
              transition: border-color 0.3s;
          }
          
          .form-group input:focus,
          .form-group textarea:focus {
              outline: none;
              border-color: #667eea;
          }
          
          .form-group textarea {
              width: 100%;
              padding: 0.6rem;
              border: 1px solid #e1e5e9;
              border-radius: 6px;
              font-size: 0.9rem;
              font-family: inherit;
              transition: border-color 0.3s;
              min-height: 720px;  //写日记模块的高度
          }
          
          /* 添加字符计数器样式 */
          .char-count {
              font-size: 0.8rem;
              color: #666;
              text-align: right;
              margin-top: 0.25rem;
          }
          
          .char-count.warning {
              color: #ffc107;
          }
          
          .char-count.error {
              color: #dc3545;
          }
          
          .save-btn {
              background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
              color: white;
              border: none;
              padding: 0.75rem 2rem;
              border-radius: 8px;
              font-size: 1rem;
              font-weight: 500;
              cursor: pointer;
              transition: transform 0.2s;
          }
          
          .save-btn:hover {
              transform: translateY(-2px);
          }
          
          .diary-list {
              background: white;
              border-radius: 8px;
              box-shadow: 0 2px 12px rgba(0,0,0,0.08);
              overflow: hidden;
              height: calc(100vh - 410px);
              display: flex;
              flex-direction: column;
          }
          
          .diary-list-header {
              padding: 1.2rem;
              margin: 0;
              color: #333;
              border-bottom: 1px solid #f0f0f0;
              background: #f8f9fa;
              font-size: 1rem;
              font-weight: 600;
          }
          
          .diary-list-content {
              flex: 1;
              overflow-y: auto;
              padding: 0;
          }
          
          .diary-date-group {
              margin-bottom: 0.8rem;
          }
          
          .date-header {
              background: #e9ecef;
              padding: 0.4rem 0.8rem;
              font-weight: 600;
              color: #495057;
              border-bottom: 1px solid #dee2e6;
              font-size: 0.8rem;
              position: sticky;
              top: 0;
              z-index: 1;
          }
          
          .diary-items {
              background: white;
          }
          
          .diary-item {
              padding: 0.6rem 0.8rem;
              border-bottom: 1px solid #f0f0f0;
              cursor: pointer;
              transition: background-color 0.2s;
              display: flex;
              flex-direction: column;
              gap: 0.2rem;
          }
          
          .diary-item:hover {
              background-color: #f8f9fa;
          }
          
          .diary-item:last-child {
              border-bottom: none;
          }
          
          .diary-title {
              color: #333;
              font-size: 0.85rem;
              font-weight: 500;
              line-height: 1.3;
              display: -webkit-box;
              -webkit-line-clamp: 2;
              -webkit-box-orient: vertical;
              overflow: hidden;
          }
          
          .diary-time {
              color: #666;
              font-size: 0.7rem;
              align-self: flex-end;
          }
          
          /* 修改: 按钮容器样式 */
          .diary-actions {
              display: flex;
              gap: 0.4rem;
              margin-top: 0.3rem;
              justify-content: flex-end;
          }
          
          .edit-btn, .delete-btn {
              padding: 0.2rem 0.4rem;
              font-size: 0.7rem;
              border: none;
              border-radius: 3px;
              cursor: pointer;
          }
          
          .edit-btn {
              background-color: #007bff;
              color: white;
          }
          
          .delete-btn {
              background-color: #dc3545;
              color: white;
          }
          
          .edit-btn:hover {
              background-color: #0056b3;
          }
          
          .delete-btn:hover {
              background-color: #c82333;
          }
          
          .empty-state {
              text-align: center;
              padding: 3rem;
              color: #666;
          }
          
          .message {
              padding: 1rem;
              margin-bottom: 1rem;
              border-radius: 8px;
              display: none;
          }
          
          .message.success {
              background: #d4edda;
              color: #155724;
              border: 1px solid #c3e6cb;
          }
          
          .message.error {
              background: #f8d7da;
              color: #721c24;
              border: 1px solid #f5c6cb;
          }
          
          /* 添加分享日记模块样式 */
          .share-section {
              margin-top: 0.8rem;
              padding-top: 0.8rem;
              border-top: 1px solid #eee;
          }
          
          .share-controls {
              display: flex;
              gap: 0.4rem;
              margin-bottom: 0.8rem;
          }
          
          .share-list {
              flex: 1;
              overflow-y: auto;
              padding: 0;
              height: calc(100vh - 520px);
          }
          
          .share-date-group {
              margin-bottom: 0.8rem;
          }
          
          .share-items {
              background: white;
          }
          
          .share-item {
              padding: 0.6rem 0.8rem;
              border-bottom: 1px solid #f0f0f0;
              cursor: pointer;
              transition: background-color 0.2s;
              display: flex;
              flex-direction: column;
              gap: 0.2rem;
          }
          
          .share-item:hover {
              background-color: #f8f9fa;
          }
          
          .share-item:last-child {
              border-bottom: none;
          }
          
          .share-title {
              color: #333;
              font-size: 0.85rem;
              font-weight: 500;
              line-height: 1.3;
              display: -webkit-box;
              -webkit-line-clamp: 2;
              -webkit-box-orient: vertical;
              overflow: hidden;
          }
          
          .share-time {
              color: #666;
              font-size: 0.7rem;
              align-self: flex-end;
          }
          
          .share-actions {
              display: flex;
              gap: 0.4rem;
              margin-top: 0.3rem;
              justify-content: flex-end;
          }
          
          .edit-share-btn, .delete-share-btn {
              padding: 0.2rem 0.4rem;
              font-size: 0.7rem;
              border: none;
              border-radius: 3px;
              cursor: pointer;
          }
          
          .edit-share-btn {
              background-color: #007bff;
              color: white;
          }
          
          .delete-share-btn {
              background-color: #dc3545;
              color: white;
          }
          
          .edit-share-btn:hover {
              background-color: #0056b3;
          }
          
          .delete-share-btn:hover {
              background-color: #c82333;
          }

          /* 添加备份恢复按钮样式 */
          .backup-section {
              margin-top: 0.8rem;
              padding-top: 0.8rem;
              border-top: 1px solid #eee;
          }
          
          .backup-controls {
              display: flex;
              gap: 0.4rem;
              margin-bottom: 0.8rem;
          }
          
          .backup-btn {
              padding: 0.4rem 0.8rem;
              border: none;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.8rem;
          }
          
          .backup-btn.primary {
              background: #28a745;
              color: white;
          }
          
          .backup-btn.secondary {
              background: #17a2b8;
              color: white;
          }
          
          .backup-list {
              max-height: 150px;
              overflow-y: auto;
              border: 1px solid #ddd;
              border-radius: 4px;
              padding: 0.4rem;
          }
          
          .backup-item {
              background: #ffffff;
              color: #969696;
              padding: 0.4rem;
              border-bottom: 1px solid #eee;
              display: flex;
              justify-content: space-between;
              align-items: center;
          }
          
          .backup-item:last-child {
              border-bottom: none;
          }
          
          .restore-btn {
              background: #ffc107;
              color: black;
              border: none;
              padding: 0.2rem 0.4rem;
              border-radius: 3px;
              cursor: pointer;
              font-size: 0.7rem;
          }
          
          .delete-backup-btn {
              background: #dc3545;
              color: white;
              border: none;
              padding: 0.2rem 0.4rem;
              border-radius: 3px;
              cursor: pointer;
              font-size: 0.7rem;
          }
          
          /* 响应式设计 */
          @media (max-width: 768px) {
              .sites {
                  width: 95%;
                  margin: 5px auto;
              }
              
              .container {
                  flex-direction: column;
                  gap: 0.8rem;
                  margin: 1rem auto;
                  padding: 0 1rem;
              }
              
              .sidebar {
                  width: 100%;
                  order: -1;
              }
              
              .diary-list {
                  height: 300px;
              }
              
              .diary-form {
                  padding: 1rem;
              }
              
              .form-group textarea {
                  min-height: 200px;
              }
              
              /* 隐藏手机端的时间显示 */
              .current-time {
                  display: none;
              }
          }
      </style>
  </head>
  <body>
  <div class="sites">
      <div class="header">
          <div class="logo">WS01 Note</div>
           <a href="/share" class="share01-btn-icon" target="_blank" title="分享目录">📂</a>
          <button class="logout-btn" onclick="logout()" title="退出登录">🚪</button>
      </div>
      
      <div class="container">
          <div id="message" class="message"></div>
          
          <div class="main-content">
              <div class="diary-form">
                   <div class="diary-form-header">
                       <div class="header-with-button">
                           <h2 class="diary-form-title">写日记</h2>
                           <div class="header-controls">
                               <select id="fontSizeSelect" class="font-size-select" title="选择字体大小">
                                   <option value="12">12px</option>
                                   <option value="14">14px</option>
                                   <option value="16" selected>16px</option>
                                   <option value="18">18px</option>
                                   <option value="20">20px</option>
                                   <option value="22">22px</option>
                               </select>
                               <button type="submit" class="save-btn-icon" title="私人保存">💾</button>
                               <button type="button" class="share-btn-icon" title="分享日记">🔗</button>
                           </div>
                       </div>
                       <div class="current-time" id="currentTime"></div>
                   </div>
                  <form id="diaryForm">
                      <div class="form-group">
                                              <!-- <label for="diaryTitle">标题</label> -->
                          <input type="text" id="diaryTitle" name="title" placeholder="标题..." required>
                      </div>
                      
                      <div class="form-group">
                                              <!-- <label for="diaryContent">内容</label> -->
                          <textarea id="diaryContent" name="content" placeholder="内容..." required></textarea>
                          <div class="char-count" id="charCount">0 / 100000</div>
                      </div>
                      
                      <!-- 删除原来的保存按钮 -->
                  </form>
              </div>
          </div>
          
          <div class="sidebar">
              <!-- 搜索框 -->
              <div class="search-section">
                  <div class="search-container">
                      <input type="text" id="searchInput" class="search-input" placeholder="搜索日记标题或内容...">
                      <button id="clearSearch" class="clear-search-btn" title="清除搜索">×</button>
                  </div>
              </div>
              
              <div class="diary-list">
                  <div class="diary-list-header">我的日记</div>
                  <div class="diary-list-content" id="diaryList">
                      <div class="empty-state">还没有日记,开始记录吧!</div>
                  </div>
              </div>
              
              <!-- 分享日记模块 -->
              <div class="share-section">
                  <div class="diary-list-header">分享日记</div>
                  <div class="share-controls">
                      <button class="backup-btn secondary" onclick="loadSharedDiaries()">刷新分享列表</button>
                  </div>
                  <div class="share-list" id="shareList">
                      <div class="empty-state">暂无分享日记</div>
                  </div>
              </div>
              
              <!-- 移动备份和恢复功能到这里 -->
              <div class="backup-section">
                  <div class="diary-list-header">数据备份与恢复</div>
                  <div class="backup-controls">
                      <button class="backup-btn primary" onclick="createBackup()">创建备份</button>
                      <button class="backup-btn secondary" onclick="loadBackups()">刷新备份列表</button>
                  </div>
                  <div class="backup-list" id="backupList">
                      <div class="empty-state">暂无备份</div>
                  </div>
              </div>
          </div>
      </div>
  
      <script>
          // 更新当前时间
          function updateTime() {
              const now = new Date();
              const timeString = now.toLocaleString('zh-CN', {
                  year: 'numeric',
                  month: '2-digit',
                  day: '2-digit',
                  hour: '2-digit',
                  minute: '2-digit',
                  second: '2-digit'
              });
              document.getElementById('currentTime').textContent = timeString;
          }
          
          // HTML转义函数
          function escapeHtml(text) {
              const div = document.createElement('div');
              div.textContent = text;
              return div.innerHTML;
          }
          
          // HTML反转义函数
          function unescapeHtml(html) {
              const div = document.createElement('div');
              div.innerHTML = html;
              return div.textContent || div.innerText || '';
          }
          
           // 添加: 更新字符计数函数
           function updateCharCount() {
               const content = document.getElementById('diaryContent');
               const charCount = document.getElementById('charCount');
               const currentLength = content.value.length;
               
               charCount.textContent = \`\${currentLength} / 100000\`;
               
               // 根据字符数量改变颜色
               if (currentLength > 1800) {
                   charCount.className = 'char-count error';
               } else if (currentLength > 1500) {
                   charCount.className = 'char-count warning';
               } else {
                   charCount.className = 'char-count';
               }
               
               // 超过限制时截断内容
               if (currentLength > 100000) {
                   content.value = content.value.substring(0, 100000);
                   charCount.textContent = '100000 / 100000';
               }
           }
           
           // 添加: 字号选择功能
           function changeFontSize() {
               const fontSizeSelect = document.getElementById('fontSizeSelect');
               const contentTextarea = document.getElementById('diaryContent');
               const selectedSize = fontSizeSelect.value;
               
               // 应用字体大小到内容区域
               contentTextarea.style.fontSize = selectedSize + 'px';
               
               // 保存用户选择到本地存储
               localStorage.setItem('ws01_font_size', selectedSize);
           }
           
           // 添加: 加载保存的字体大小
           function loadFontSize() {
               const savedSize = localStorage.getItem('ws01_font_size');
               const fontSizeSelect = document.getElementById('fontSizeSelect');
               const contentTextarea = document.getElementById('diaryContent');
               
               if (savedSize) {
                   fontSizeSelect.value = savedSize;
                   contentTextarea.style.fontSize = savedSize + 'px';
               } else {
                   // 默认字体大小
                   contentTextarea.style.fontSize = '14px';
               }
           }
          
          // 每秒更新时间
          setInterval(updateTime, 1000);
          updateTime();
          
          // 检查登录状态
          function checkAuth() {
              const token = localStorage.getItem('ws01_token');
              if (!token) {
                  window.location.href = '/login';
                  return false;
              }
              return true;
          }
          
          // 显示消息
          function showMessage(message, type = 'success') {
              const messageDiv = document.getElementById('message');
              messageDiv.textContent = message;
              messageDiv.className = \`message \${type}\`;
              messageDiv.style.display = 'block';
              
              setTimeout(() => {
                  messageDiv.style.display = 'none';
              }, 3000);
          }
          
          // 加载日记列表
          async function loadDiaries() {
              try {
                  const response = await fetch('/api/diary', {
                      headers: {
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      }
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      allDiaries = result.diaries; // 存储所有日记数据
                      
                      // 检查是否有搜索条件,如果有则重新执行搜索
                      const searchTerm = document.getElementById('searchInput').value.trim();
                      if (searchTerm) {
                          performSearch(); // 重新执行搜索
                      } else {
                          filteredDiaries = [...allDiaries]; // 初始化过滤后的数据
                          displayDiaries(filteredDiaries);
                      }
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('加载日记失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          // 显示日记列表
          function displayDiaries(diaries) {
              const diaryList = document.getElementById('diaryList');
              const searchTerm = document.getElementById('searchInput').value.trim();
              
              if (diaries.length === 0) {
                  if (searchTerm) {
                      diaryList.innerHTML = '<div class="empty-state">没有找到匹配的日记</div>';
                  } else {
                      diaryList.innerHTML = '<div class="empty-state">还没有日记,开始记录吧!</div>';
                  }
                  return;
              }
              
              // 按日期分组日记
              const groupedDiaries = {};
              diaries.forEach(diary => {
                  const date = new Date(diary.date).toLocaleDateString('zh-CN');
                  if (!groupedDiaries[date]) {
                      groupedDiaries[date] = [];
                  }
                  groupedDiaries[date].push(diary);
              });
              
              // 生成HTML
              let html = '';
              const sortedDates = Object.keys(groupedDiaries).sort((a, b) => new Date(b) - new Date(a));
              
              sortedDates.forEach(date => {
                  html += \`<div class="diary-date-group">
                      <div class="date-header">\${date}</div>
                      <div class="diary-items">\`;
                  
                  groupedDiaries[date].forEach(diary => {
                      // 限制标题显示长度
                      const maxTitleLength = 15;
                      const displayTitle = diary.title.length > maxTitleLength 
                          ? diary.title.substring(0, maxTitleLength) + '...' 
                          : diary.title;
                      
                      html += \`<div class="diary-item" onclick="viewDiary('\${diary.id}')">
                          <div style="display: flex; justify-content: space-between; align-items: center;">
                              <div class="diary-title">\${displayTitle}</div>
                              <div class="diary-actions">
                                  <button class="edit-btn" onclick="editDiary(event, '\${diary.id}')" title="编辑">&#9998;</button>
                                  <button class="delete-btn" onclick="deleteDiary(event, '\${diary.id}')" title="删除">&#128465;</button>
                              </div>
                          </div>
                          <!-- 删除时间显示 -->
                      </div>\`;
                  });
  
                  html += \`</div></div>\`;
              });
              
              diaryList.innerHTML = html;
          }
          
          // 添加: 编辑日记功能
          function editDiary(event, diaryId) {
              event.stopPropagation(); // 防止触发查看日记
              
              // 查找要编辑的日记
              fetch('/api/diary', {
                  headers: {
                      'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                  }
              })
              .then(response => response.json())
              .then(result => {
                  if (result.success) {
                      const diary = result.diaries.find(d => d.id === diaryId);
                      if (diary) {
                          // 填充表单(反转义HTML字符)
                          document.getElementById('diaryTitle').value = unescapeHtml(diary.title);
                          document.getElementById('diaryContent').value = unescapeHtml(diary.content);
                          
                          // 保存当前编辑的日记ID到表单属性中
                          document.getElementById('diaryForm').setAttribute('data-edit-id', diaryId);
                          
                          // 更改按钮文字为"更新日记"
                          document.querySelector('.save-btn').textContent = '更新日记';
                          
                          // 滚动到表单顶部
                          document.querySelector('.diary-form').scrollIntoView({ behavior: 'smooth' });
                      } else {
                          showMessage('找不到要编辑的日记', 'error');
                      }
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('加载失败: ' + result.message, 'error');
                      }
                  }
              })
              .catch(error => {
                  showMessage('网络错误,请重试', 'error');
              });
          }
          
          // 添加: 删除日记功能
          function deleteDiary(event, diaryId) {
              event.stopPropagation(); // 防止触发查看日记
              
              if (!confirm('确定要删除这篇日记吗?')) {
                  return;
              }
              
              fetch('/api/diary', {
                  method: 'DELETE',
                  headers: {
                      'Content-Type': 'application/json',
                      'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                  },
                  body: JSON.stringify({ id: diaryId })
              })
              .then(response => response.json())
              .then(result => {
                  if (result.success) {
                      showMessage('日记删除成功!');
                      loadDiaries(); // 重新加载日记列表,这会更新allDiaries和filteredDiaries
                      
                      // 如果正在编辑被删除的日记,重置表单
                      const form = document.getElementById('diaryForm');
                      if (form.getAttribute('data-edit-id') === diaryId) {
                          form.reset();
                          form.removeAttribute('data-edit-id');
                          document.querySelector('.save-btn').textContent = '保存日记';
                      }
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('删除失败: ' + result.message, 'error');
                      }
                  }
              })
              .catch(error => {
                  showMessage('网络错误,请重试', 'error');
              });
          }
          
          // 保存日记
          document.getElementById('diaryForm').addEventListener('submit', async (e) => {
              e.preventDefault();
              
              if (!checkAuth()) return;
              
              const title = document.getElementById('diaryTitle').value;
              const content = document.getElementById('diaryContent').value;
              const editId = document.getElementById('diaryForm').getAttribute('data-edit-id');
              const editShareId = document.getElementById('diaryForm').getAttribute('data-edit-share-id');
              
              // 对HTML特殊字符进行转义
              const escapedTitle = escapeHtml(title);
              const escapedContent = escapeHtml(content);
              
              try {
                  const method = editId ? 'PUT' : 'POST';
                  const body = editId 
                      ? JSON.stringify({ id: editId, title: escapedTitle, content: escapedContent }) 
                      : JSON.stringify({ title: escapedTitle, content: escapedContent, editShareId: editShareId || null });
                  
                  const response = await fetch('/api/diary', {
                      method: method,
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      },
                      body: body
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      if (editId) {
                          showMessage('日记更新成功!');
                          // 重置表单状态
                          document.getElementById('diaryForm').removeAttribute('data-edit-id');
                          document.querySelector('.save-btn').textContent = '保存日记';
                      } else {
                          showMessage('日记保存成功!');
                          document.getElementById('diaryForm').reset();
                          
                          // 如果是从分享日记编辑而来,重置表单状态
                          if (editShareId) {
                              document.getElementById('diaryForm').removeAttribute('data-edit-share-id');
                          }
                      }
                      
                      // 刷新两个列表
                      loadDiaries();
                      loadSharedDiaries();
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('保存失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          });
          
          // 添加: 为保存按钮图标添加点击事件监听器
          document.querySelector('.save-btn-icon').addEventListener('click', function() {
              document.getElementById('diaryForm').dispatchEvent(new Event('submit'));
          });
          
          // 添加: 为分享按钮图标添加点击事件监听器
          document.querySelector('.share-btn-icon').addEventListener('click', function() {
              shareDiary();
          });
          
          // 分享日记功能
          async function shareDiary() {
              if (!checkAuth()) return;
              
              const title = document.getElementById('diaryTitle').value;
              const content = document.getElementById('diaryContent').value;
              const editShareId = document.getElementById('diaryForm').getAttribute('data-edit-share-id');
              const editDiaryId = document.getElementById('diaryForm').getAttribute('data-edit-id');
              
              if (!title.trim() || !content.trim()) {
                  showMessage('请先填写标题和内容', 'error');
                  return;
              }
              
              // 对HTML特殊字符进行转义
              const escapedTitle = escapeHtml(title);
              const escapedContent = escapeHtml(content);
              
              try {
                  const method = editShareId ? 'PUT' : 'POST';
                  const body = editShareId 
                      ? JSON.stringify({ shareId: editShareId, title: escapedTitle, content: escapedContent }) 
                      : JSON.stringify({ title: escapedTitle, content: escapedContent, editDiaryId: editDiaryId || null });
                  
                  const response = await fetch('/api/diary/share', {
                      method: method,
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      },
                      body: body
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      if (editShareId) {
                          // 更新分享日记
                          const shareUrl = \`\${window.location.origin}/share/\${editShareId}\`;
                          showMessage(\`分享日记更新成功!链接:\${shareUrl}\`, 'success');
                          
                          // 重置表单状态
                          document.getElementById('diaryForm').removeAttribute('data-edit-share-id');
                      } else {
                          // 新建分享日记
                          const shareUrl = \`\${window.location.origin}/share/\${result.shareId}\`;
                          showMessage(\`分享成功!链接:\${shareUrl}\`, 'success');
                          
                          // 如果是从我的日记编辑而来,重置表单状态
                          if (editDiaryId) {
                              document.getElementById('diaryForm').removeAttribute('data-edit-id');
                          }
                      }
                      
                      // 可选:复制链接到剪贴板
                      if (navigator.clipboard) {
                          const shareUrl = editShareId 
                              ? \`\${window.location.origin}/share/\${editShareId}\`
                              : \`\${window.location.origin}/share/\${result.shareId}\`;
                          navigator.clipboard.writeText(shareUrl).then(() => {
                              console.log('分享链接已复制到剪贴板');
                          });
                      }
                      
                      // 刷新两个列表
                      loadDiaries();
                      loadSharedDiaries();
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('分享失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          // 查看具体日记页面
          function viewDiary(diaryId) {
              window.location.href = \`/diary/\${diaryId}\`;
          }
          
          // 退出登录
          function logout() {
              localStorage.removeItem('ws01_token');
              window.location.href = '/login';
          }
          
          // 添加备份相关函数
          async function createBackup() {
              try {
                  const response = await fetch('/api/diary/backup', {
                      method: 'POST',
                      headers: {
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      }
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      showMessage('备份创建成功!');
                      loadBackups();
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('备份创建失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          async function loadBackups() {
              try {
                  const response = await fetch('/api/diary/backups', {
                      headers: {
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      }
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      displayBackups(result.backups);
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('加载备份列表失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          function displayBackups(backups) {
              const backupList = document.getElementById('backupList');
              
              if (backups.length === 0) {
                  backupList.innerHTML = '<div class="empty-state">暂无备份</div>';
                  return;
              }
              
              let html = '';
              backups.forEach(backup => {
                  const date = new Date(backup.timestamp).toLocaleString('zh-CN');
                  html += \`
                  <div class="backup-item">
                      <div>
                          <div>备份 #\${backup.id}</div>
                          <div style="font-size: 0.8rem; color: #666;">\${date}</div>
                          <div style="font-size: 0.8rem; color: #666;">包含 \${backup.count} 条日记\${backup.shareCount > 0 ? ',' + backup.shareCount + ' 条分享日记' : ''}</div>
                      </div>
                      <div>
                          <button class="restore-btn" onclick="restoreBackup('\${backup.id}')">恢复</button>
                          <button class="delete-backup-btn" onclick="deleteBackup('\${backup.id}')">删除</button>
                      </div>
                  </div>\`;
              });
              
              backupList.innerHTML = html;
          }
          
          async function restoreBackup(backupId) {
              if (!confirm('确定要恢复此备份吗?这将覆盖当前所有日记数据!')) {
                  return;
              }
              
              try {
                  const response = await fetch('/api/diary/restore', {
                      method: 'POST',
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      },
                      body: JSON.stringify({ backupId })
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      showMessage('数据恢复成功!');
                      loadDiaries(); // 重新加载日记列表
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('数据恢复失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          async function deleteBackup(backupId) {
              if (!confirm('确定要删除此备份吗?')) {
                  return;
              }
              
              try {
                  const response = await fetch('/api/diary/backup', {
                      method: 'DELETE',
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      },
                      body: JSON.stringify({ backupId })
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      showMessage('备份删除成功!');
                      loadBackups(); // 重新加载备份列表
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('备份删除失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          // 搜索相关变量
          let allDiaries = []; // 存储所有日记数据
          let filteredDiaries = []; // 存储过滤后的日记数据
          
          // 搜索功能
          async function performSearch() {
              const searchTerm = document.getElementById('searchInput').value.toLowerCase().trim();
              const clearBtn = document.getElementById('clearSearch');
              
              if (searchTerm === '') {
                  // 如果搜索框为空,显示所有日记
                  filteredDiaries = [...allDiaries];
                  clearBtn.classList.add('hidden');
                  displayDiaries(filteredDiaries);
              } else {
                  // 搜索我的日记
                  const myDiaryResults = allDiaries.filter(diary => 
                      diary.title.toLowerCase().includes(searchTerm) || 
                      diary.content.toLowerCase().includes(searchTerm)
                  );
                  
                  // 搜索分享日记
                  try {
                      const response = await fetch('/api/diary/shares', {
                          headers: {
                              'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                          }
                      });
                      
                      if (response.ok) {
                          const result = await response.json();
                          const shareResults = result.shares.filter(share => 
                              share.title.toLowerCase().includes(searchTerm) || 
                              share.content.toLowerCase().includes(searchTerm)
                          );
                          
                          // 合并搜索结果
                          const combinedResults = [
                              ...myDiaryResults.map(diary => ({ ...diary, type: 'private' })),
                              ...shareResults.map(share => ({ ...share, type: 'shared' }))
                          ];
                          
                          // 按日期排序
                          combinedResults.sort((a, b) => new Date(b.date) - new Date(a.date));
                          
                          filteredDiaries = combinedResults;
                      } else {
                          // 如果获取分享日记失败,只显示我的日记搜索结果
                          filteredDiaries = myDiaryResults.map(diary => ({ ...diary, type: 'private' }));
                      }
                  } catch (error) {
                      // 如果网络错误,只显示我的日记搜索结果
                      filteredDiaries = myDiaryResults.map(diary => ({ ...diary, type: 'private' }));
                  }
                  
                  clearBtn.classList.remove('hidden');
                  displaySearchResults(filteredDiaries);
              }
          }
          
          // 显示搜索结果(包含我的日记和分享日记)
          function displaySearchResults(results) {
              const diaryList = document.getElementById('diaryList');
              const searchTerm = document.getElementById('searchInput').value.trim();
              
              if (results.length === 0) {
                  diaryList.innerHTML = '<div class="empty-state">没有找到匹配的日记</div>';
                  return;
              }
              
              // 按日期分组日记
              const groupedDiaries = {};
              results.forEach(diary => {
                  const date = new Date(diary.date).toLocaleDateString('zh-CN');
                  if (!groupedDiaries[date]) {
                      groupedDiaries[date] = [];
                  }
                  groupedDiaries[date].push(diary);
              });
              
              // 生成HTML
              let html = '';
              const sortedDates = Object.keys(groupedDiaries).sort((a, b) => new Date(b) - new Date(a));
              
              sortedDates.forEach(date => {
                  html += \`<div class="diary-date-group">
                      <div class="date-header">\${date}</div>
                      <div class="diary-items">\`;
                  
                  groupedDiaries[date].forEach(diary => {
                      // 限制标题显示长度
                      const maxTitleLength = 15;
                      const displayTitle = diary.title.length > maxTitleLength 
                          ? diary.title.substring(0, maxTitleLength) + '...' 
                          : diary.title;
                      
                      // 根据类型显示不同的操作按钮
                      let actionButtons = '';
                      if (diary.type === 'private') {
                          actionButtons = \`
                              <div class="diary-actions">
                                  <button class="edit-btn" onclick="editDiary(event, '\${diary.id}')" title="编辑">&#9998;</button>
                                  <button class="delete-btn" onclick="deleteDiary(event, '\${diary.id}')" title="删除">&#128465;</button>
                              </div>\`;
                      } else if (diary.type === 'shared') {
                          actionButtons = \`
                              <div class="diary-actions">
                                  <button class="edit-btn" onclick="editSharedDiary(event, '\${diary.id}')" title="编辑">&#9998;</button>
                                  <button class="delete-btn" onclick="deleteSharedDiary(event, '\${diary.id}')" title="删除">&#128465;</button>
                              </div>\`;
                      }
                      
                      // 根据类型设置点击事件
                      const clickEvent = diary.type === 'private' 
                          ? \`onclick="viewDiary('\${diary.id}')"\`
                          : \`onclick="viewSharedDiary('\${diary.shareUrl}')"\`;
                      
                      html += \`<div class="diary-item" \${clickEvent}>
                          <div style="display: flex; justify-content: space-between; align-items: center;">
                              <div class="diary-title">\${displayTitle} \${diary.type === 'shared' ? '<span style="color: #28a745; font-size: 0.7rem;">[分享]</span>' : ''}</div>
                              \${actionButtons}
                          </div>
                      </div>\`;
                  });
  
                  html += \`</div></div>\`;
              });
              
              diaryList.innerHTML = html;
          }
          
          // 清除搜索
          function clearSearch() {
              document.getElementById('searchInput').value = '';
              document.getElementById('clearSearch').classList.add('hidden');
              filteredDiaries = [...allDiaries];
              displayDiaries(filteredDiaries);
          }
          
          // 加载分享日记列表
          async function loadSharedDiaries() {
              try {
                  const response = await fetch('/api/diary/shares', {
                      headers: {
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      }
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      displaySharedDiaries(result.shares);
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('加载分享列表失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          // 显示分享日记列表
          function displaySharedDiaries(shares) {
              const shareList = document.getElementById('shareList');
              
              if (shares.length === 0) {
                  shareList.innerHTML = '<div class="empty-state">暂无分享日记</div>';
                  return;
              }
              
              // 按日期分组分享日记
              const groupedShares = {};
              shares.forEach(share => {
                  const date = new Date(share.date).toLocaleDateString('zh-CN');
                  if (!groupedShares[date]) {
                      groupedShares[date] = [];
                  }
                  groupedShares[date].push(share);
              });
              
              // 生成HTML
              let html = '';
              const sortedDates = Object.keys(groupedShares).sort((a, b) => new Date(b) - new Date(a));
              
              sortedDates.forEach(date => {
                  html += \`<div class="share-date-group">
                      <div class="date-header">\${date}</div>
                      <div class="share-items">\`;
                  
                  groupedShares[date].forEach(share => {
                      // 限制标题显示长度
                      const maxTitleLength = 15;
                      const displayTitle = share.title.length > maxTitleLength 
                          ? share.title.substring(0, maxTitleLength) + '...' 
                          : share.title;
                      
                      html += \`<div class="share-item" onclick="viewSharedDiary('\${share.shareUrl}')">
                          <div style="display: flex; justify-content: space-between; align-items: center;">
                              <div class="share-title">\${displayTitle}</div>
                              <div class="share-actions">
                                  <button class="edit-share-btn" onclick="editSharedDiary(event, '\${share.id}')" title="编辑">&#9998;</button>
                                  <button class="delete-share-btn" onclick="deleteSharedDiary(event, '\${share.id}')" title="删除">&#128465;</button>
                              </div>
                          </div>
                      </div>\`;
                  });
  
                  html += \`</div></div>\`;
              });
              
              shareList.innerHTML = html;
          }
          
          // 查看分享日记
          function viewSharedDiary(shareUrl) {
              window.open(shareUrl, '_blank');
          }
          
          // 编辑分享日记
          async function editSharedDiary(event, shareId) {
              event.stopPropagation(); // 防止触发查看日记
              
              try {
                  // 获取分享日记内容
                  const response = await fetch(\`/api/share/\${shareId}\`);
                  
                  if (response.ok) {
                      const shareData = await response.json();
                      
                      // 填充表单(反转义HTML字符)
                      document.getElementById('diaryTitle').value = unescapeHtml(shareData.title);
                      document.getElementById('diaryContent').value = unescapeHtml(shareData.content);
                      
                      // 保存当前编辑的分享ID到表单属性中
                      document.getElementById('diaryForm').setAttribute('data-edit-share-id', shareId);
                      
                      // 滚动到表单顶部
                      document.querySelector('.diary-form').scrollIntoView({ behavior: 'smooth' });
                      
                      showMessage('分享日记已加载到编辑区域,修改后点击分享按钮更新', 'success');
                  } else {
                      showMessage('加载分享日记失败', 'error');
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }
          
          // 删除分享日记
          async function deleteSharedDiary(event, shareId) {
              event.stopPropagation(); // 防止触发查看日记
              if (!confirm('确定要删除这个分享日记吗?')) {
                  return;
              }
              
              try {
                  const response = await fetch('/api/diary/share', {
                      method: 'DELETE',
                      headers: {
                          'Content-Type': 'application/json',
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      },
                      body: JSON.stringify({ shareId })
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      showMessage('分享日记删除成功!');
                      loadSharedDiaries(); // 重新加载分享列表
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showMessage('删除失败: ' + result.message, 'error');
                      }
                  }
              } catch (error) {
                  showMessage('网络错误,请重试', 'error');
              }
          }

          // 页面加载时检查认证并加载日记和备份
          if (checkAuth()) {
              loadDiaries();
              loadBackups(); // 加载备份列表
              loadSharedDiaries(); // 加载分享日记列表
          }
          
           // 添加内容输入事件监听器
           document.addEventListener('DOMContentLoaded', function() {
               const contentTextarea = document.getElementById('diaryContent');
               const fontSizeSelect = document.getElementById('fontSizeSelect');
               const searchInput = document.getElementById('searchInput');
               const clearSearchBtn = document.getElementById('clearSearch');
               
               if (contentTextarea) {
                   contentTextarea.addEventListener('input', updateCharCount);
               }
               
               if (fontSizeSelect) {
                   fontSizeSelect.addEventListener('change', changeFontSize);
               }
               
               // 添加搜索功能事件监听器
               if (searchInput) {
                   searchInput.addEventListener('input', performSearch);
               }
               
               if (clearSearchBtn) {
                   clearSearchBtn.addEventListener('click', clearSearch);
               }
               
               // 加载保存的字体大小
               loadFontSize();
           });
      </script>
  </body>
  </html>`;
  }
  
  // 日记详情页面
  function getDiaryDetailPage(diaryId) {
    return `
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WS01 Note - 日记详情</title>
      <style>
          * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
          }
          
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: #f8f9fa;
              min-height: 100vh;
          }
          
  .sites {
  width:1000px;
  background:#F2F2F2;
  border:1px solid rgba(0,0,0,.06);
  margin:10px auto;
  padding:0px;
  color: white;
  border-radius: 6px;
  }
  
  .sites01 {
  width:1280px;
  background:;
  border:2px solid auto;
  margin:15px auto;
  padding:0px;
  }
  
  .sites dl {
  height:36px;
  line-height:36px;
  display:block;
  margin:0;
  }
  
  .sites dl.alt {
  background:#c5dff6;
  border-top:1px solid #ffffff;
  border-bottom:1px solid #ffffff;
  }
  
  .sites dl.alt2 {
  background:#dcecfa;
  border-top:1px solid #ffffff;
  border-bottom:1px solid #ffffff;
  }
  
  .sites dt,.sites dd {
  text-align:center;
  display:block;
  float:left;
  }
  
  .sites dt {
  width:60px;
  }
  
  .sites dd {
  width:90px;
  margin:0;
  }
  
  .header {
    background: #D4D4D4;
    padding: 0.8rem 1.5rem;
    box-shadow: 0 1px 6px rgba(0,0,0,0.08);
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
}
          
          .logo {
              font-size: 1.5rem;
              font-weight: 400;
              color: #333;
          }
          
          .back-btn {
            background: #1C86EE;
            color: white;
            border: none;
            padding: 0.4rem 0.8rem;
            border-radius: 4px;
            cursor: pointer;
            font-size: 0.8rem;
            position: absolute;
            right: 2.6rem;
        }
          
           .back-btn:hover {
               background: #1874CD;
           }
           
           .header-controls {
               display: flex;
               align-items: center;
               gap: 0.5rem;
           }
           
           .font-size-select {
               padding: 0.3rem 0.5rem;
               border: 1px solid #e1e5e9;
               border-radius: 4px;
               font-size: 0.8rem;
               background: white;
               cursor: pointer;
               transition: border-color 0.3s;
           }
           
           .font-size-select:focus {
               outline: none;
               border-color: #667eea;
           }
           
           .font-size-select:hover {
               border-color: #667eea;
           }
          
          .container {
              max-width: 960px;
              margin: 1.5rem auto;
              padding: 0 1.5rem;
          }
          
          .diary-detail {
              background: white;
              padding: 1.5rem;
              border-radius: 8px;
              box-shadow: 0 2px 12px rgba(0,0,0,0.08);
              max-height: 900px;
              overflow-y: auto;
          }
          
          .diary-header {
              border-bottom: 1px solid #e9ecef;
              padding-bottom: 0.8rem;
              margin-bottom: 1.2rem;
          }
          
          .diary-title {
              font-size: 1.5rem;
              color: #333;
              margin-bottom: 0.4rem;
              font-weight: 600;
              word-wrap: break-word;
          }
          
          .diary-date {
              color: #666;
              font-size: 0.8rem;
          }
          
          .diary-content {
              color: #333;
              line-height: 1.6;
              white-space: pre-wrap;
              font-size: 0.9rem;
              word-wrap: break-word;
              overflow-wrap: break-word;
              word-break: break-all;
              border: 1px dashed #ccc;
              padding: 0.8rem;
              border-radius: 4px;
          }
          
          .loading {
              text-align: center;
              padding: 2rem;
              color: #666;
          }
          
          .error {
              text-align: center;
              padding: 2rem;
              color: #e74c3c;
          }
          
          /* 添加复制按钮样式 */
          .copy-btn {
              background: #007bff;
              color: white;
              border: none;
              padding: 0.4rem 0.8rem;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.8rem;
              margin-left: 0.8rem;
          }
          
          .copy-btn:hover {
              background: #0056b3;
          }
          
          .title-container {
              display: flex;
              align-items: center;
              flex-wrap: wrap;
          }
          
          .notification {
              position: fixed;
              top: 15px;
              right: 15px;
              background: #28a745;
              color: white;
              padding: 0.8rem;
              border-radius: 4px;
              box-shadow: 0 2px 8px rgba(0,0,0,0.12);
              display: none;
              z-index: 1000;
              font-size: 0.8rem;
          }
      </style>
  </head>
  <body>
  <div class="sites">
       <div class="header">
           <div class="logo">WS01 Note</div>
           <div class="header-controls">
               <select id="fontSizeSelect" class="font-size-select" title="选择字体大小">
                   <option value="12">12px</option>
                   <option value="14">14px</option>
                   <option value="16" selected>16px</option>
                   <option value="18">18px</option>
                   <option value="20">20px</option>
                   <option value="22">22px</option>
               </select>
               <a href="/diary" class="back-btn">← 返回</a>
           </div>
       </div>
      
      <div class="container">
          <div id="diaryDetail" class="diary-detail">
              <div class="loading">加载中...</div>
          </div>
      </div>
      
      <div id="notification" class="notification">内容已复制到剪贴板</div>
  
      <script>
          const diaryId = '${diaryId}';
          
          // 检查登录状态
          function checkAuth() {
              const token = localStorage.getItem('ws01_token');
              if (!token) {
                  window.location.href = '/login';
                  return false;
              }
              return true;
          }
          
          // 加载日记详情
          async function loadDiaryDetail() {
              if (!checkAuth()) return;
              
              try {
                  const response = await fetch('/api/diary', {
                      headers: {
                          'Authorization': \`Bearer \${localStorage.getItem('ws01_token')}\`
                      }
                  });
                  
                  const result = await response.json();
                  
                  if (result.success) {
                      const diary = result.diaries.find(d => d.id === diaryId);
                      if (diary) {
                          displayDiaryDetail(diary);
                      } else {
                          showError('日记不存在');
                      }
                  } else {
                      if (result.message === '未授权') {
                          window.location.href = '/login';
                      } else {
                          showError('加载失败: ' + result.message);
                      }
                  }
              } catch (error) {
                  showError('网络错误,请重试');
              }
          }
          
           // 显示日记详情
           function displayDiaryDetail(diary) {
               const diaryDetail = document.getElementById('diaryDetail');
               const date = new Date(diary.date).toLocaleString('zh-CN');
               
               // 限制标题显示长度
               const maxTitleLength = 15;
               const displayTitle = diary.title.length > maxTitleLength 
                   ? diary.title.substring(0, maxTitleLength) + '...' 
                   : diary.title;
               
               diaryDetail.innerHTML = \`
                   <div class="diary-header">
                       <div class="title-container">
                           <h1 class="diary-title">\${displayTitle}</h1>
                           <button class="copy-btn" onclick="copyContent('\${diary.content.replace(/'/g, "\\'").replace(/\\n/g, '\\\\n')}')">复制内容</button>
                       </div>
                       <div class="diary-date">\${date}</div>
                   </div>
                   <div class="diary-content" id="diaryContent"></div>
               \`;
               
               // 使用textContent设置内容,避免HTML标签被解析
               document.getElementById('diaryContent').textContent = diary.content;
               
               // 应用保存的字体大小
               loadFontSize();
           }
           
           // 添加: 字号选择功能
           function changeFontSize() {
               const fontSizeSelect = document.getElementById('fontSizeSelect');
               const contentDiv = document.getElementById('diaryContent');
               const selectedSize = fontSizeSelect.value;
               
               if (contentDiv) {
                   // 应用字体大小到内容区域
                   contentDiv.style.fontSize = selectedSize + 'px';
                   
                   // 保存用户选择到本地存储
                   localStorage.setItem('ws01_detail_font_size', selectedSize);
               }
           }
           
           // 添加: 加载保存的字体大小
           function loadFontSize() {
               const savedSize = localStorage.getItem('ws01_detail_font_size');
               const fontSizeSelect = document.getElementById('fontSizeSelect');
               const contentDiv = document.getElementById('diaryContent');
               
               if (savedSize && fontSizeSelect && contentDiv) {
                   fontSizeSelect.value = savedSize;
                   contentDiv.style.fontSize = savedSize + 'px';
               } else if (contentDiv) {
                   // 默认字体大小16px
                   contentDiv.style.fontSize = '16px';
               }
           }
          
          // 显示错误
          function showError(message) {
              const diaryDetail = document.getElementById('diaryDetail');
              diaryDetail.innerHTML = \`<div class="error">\${message}</div>\`;
          }
          
          // 复制内容功能
          function copyContent(content) {
              navigator.clipboard.writeText(content).then(() => {
                  const notification = document.getElementById('notification');
                  notification.style.display = 'block';
                  
                  setTimeout(() => {
                      notification.style.display = 'none';
                  }, 100000);
              }).catch(err => {
                  console.error('复制失败:', err);
                  const notification = document.getElementById('notification');
                  notification.textContent = '复制失败';
                  notification.style.backgroundColor = '#dc3545';
                  notification.style.display = 'block';
                  
                  setTimeout(() => {
                      notification.style.display = 'none';
                      // 恢复默认文本和颜色
                      notification.textContent = '内容已复制到剪贴板';
                      notification.style.backgroundColor = '#28a745';
                  }, 100000);
              });
          }
          
          // 复制分享内容功能
          function copyShareContent() {
              if (window.shareContent) {
                  copyContent(window.shareContent);
              } else {
                  // 如果全局变量不存在,尝试从DOM元素获取
                  const contentElement = document.getElementById('shareContent');
                  if (contentElement) {
                      copyContent(contentElement.textContent);
                  } else {
                      console.error('无法获取分享内容');
                      const notification = document.getElementById('notification');
                      notification.textContent = '复制失败:无法获取内容';
                      notification.style.backgroundColor = '#dc3545';
                      notification.style.display = 'block';
                      
                      setTimeout(() => {
                          notification.style.display = 'none';
                      }, 3000);
                  }
              }
          }
          
           // 页面加载时加载日记详情
           loadDiaryDetail();
           
           // 添加字号选择事件监听器
           document.addEventListener('DOMContentLoaded', function() {
               const fontSizeSelect = document.getElementById('fontSizeSelect');
               if (fontSizeSelect) {
                   fontSizeSelect.addEventListener('change', changeFontSize);
               }
           });
      </script>
  </body>
  </html>`;
  }
  
  // 分享日记目录页面
  function getShareIndexPage() {
    return `
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WS01 Note - 分享目录</title>
      <style>
          * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
          }
          
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: #f8f9fa;
              min-height: 100vh;
          }
          
          .sites {
              width: 1000px;
              background: #F2F2F2;
              border: 1px solid rgba(0,0,0,.06);
              margin: 10px auto;
              padding: 0px;
              color: white;
              border-radius: 6px;
          }
          
          .header {
              background: #D4D4D4;
              padding: 0.8rem 1.5rem;
              box-shadow: 0 1px 6px rgba(0,0,0,0.08);
              display: flex;
              justify-content: center;
              align-items: center;
              position: relative;
          }
          
          .logo {
              font-size: 1.5rem;
              font-weight: 400;
              color: #333;
          }
          
          .back-btn {
              background: #1C86EE;
              color: white;
              border: none;
              padding: 0.4rem 0.8rem;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.8rem;
              position: absolute;
              right: 2.6rem;
              text-decoration: none;
              display: inline-block;
          }
          
          .back-btn:hover {
              background: #1874CD;
          }
          
          .container {
              max-width: 960px;
              margin: 1.5rem auto;
              padding: 0 1.5rem;
          }
          
          .share-index {
              background: white;
              padding: 1.5rem;
              border-radius: 8px;
              box-shadow: 0 2px 12px rgba(0,0,0,0.08);
          }
          
          .share-index-header {
              border-bottom: 1px solid #e9ecef;
              padding-bottom: 0.8rem;
              margin-bottom: 1.2rem;
          }
          
          .share-index-title {
              font-size: 1.5rem;
              color: #333;
              margin-bottom: 0.4rem;
              font-weight: 600;
          }
          
          .share-index-subtitle {
              color: #666;
              font-size: 0.9rem;
          }
          
          .share-list {
              display: grid;
              gap: 1rem;
          }
          
          .share-date-group {
              margin-bottom: 1.5rem;
          }
          
          .date-header {
              background: #e9ecef;
              padding: 0.4rem 0.8rem;
              font-weight: 600;
              color: #495057;
              border-bottom: 1px solid #dee2e6;
              font-size: 0.9rem;
              position: sticky;
              top: 0;
              z-index: 1;
              border-radius: 4px 4px 0 0;
          }
          
          .share-items {
              background: white;
              border: 1px solid #e9ecef;
              border-top: none;
              border-radius: 0 0 4px 4px;
          }
          
          .share-item {
              padding: 1rem;
              border-bottom: 1px solid #f0f0f0;
              cursor: pointer;
              transition: background-color 0.2s;
              display: flex;
              justify-content: space-between;
              align-items: center;
          }
          
          .share-item:hover {
              background-color: #f8f9fa;
          }
          
          .share-item:last-child {
              border-bottom: none;
          }
          
          .share-item-info {
              flex: 1;
              min-width: 0;
          }
          
          .share-item-title {
              color: #333;
              font-size: 1rem;
              font-weight: 500;
              margin-bottom: 0.3rem;
              line-height: 1.4;
          }
          
          .share-item-preview {
              color: #666;
              font-size: 0.85rem;
              line-height: 1.4;
              display: -webkit-box;
              -webkit-line-clamp: 2;
              -webkit-box-orient: vertical;
              overflow: hidden;
              margin-bottom: 0.3rem;
          }
          
          .share-item-date {
              color: #999;
              font-size: 0.75rem;
          }
          
          .share-item-actions {
              display: flex;
              gap: 0.5rem;
              margin-left: 1rem;
          }
          
          .view-btn {
              background: #007bff;
              color: white;
              border: none;
              padding: 0.4rem 0.8rem;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.8rem;
              text-decoration: none;
              display: inline-block;
          }
          
          .view-btn:hover {
              background: #0056b3;
          }
          
          .loading {
              text-align: center;
              padding: 2rem;
              color: #666;
          }
          
          .error {
              text-align: center;
              padding: 2rem;
              color: #e74c3c;
          }
          
          .empty-state {
              text-align: center;
              padding: 3rem;
              color: #666;
          }
          
          .empty-state-icon {
              font-size: 3rem;
              margin-bottom: 1rem;
              opacity: 0.5;
          }
          
          /* 分页控件样式 */
          .pagination {
              display: flex;
              justify-content: center;
              align-items: center;
              margin-top: 2rem;
              padding: 1rem 0;
              border-top: 1px solid #e9ecef;
          }
          
          .pagination-info {
              margin-right: 1rem;
              color: #666;
              font-size: 0.9rem;
          }
          
          .pagination-controls {
              display: flex;
              gap: 0.5rem;
              align-items: center;
          }
          
          .pagination-btn {
              background: #007bff;
              color: white;
              border: none;
              padding: 0.5rem 0.8rem;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.9rem;
              transition: background-color 0.2s;
          }
          
          .pagination-btn:hover:not(:disabled) {
              background: #0056b3;
          }
          
          .pagination-btn:disabled {
              background: #6c757d;
              cursor: not-allowed;
              opacity: 0.6;
          }
          
          .pagination-current {
              background: #28a745;
              color: white;
              border: none;
              padding: 0.5rem 0.8rem;
              border-radius: 4px;
              font-size: 0.9rem;
              font-weight: 600;
          }
          
          .pagination-jump {
              display: flex;
              align-items: center;
              gap: 0.5rem;
              margin-left: 1rem;
              color: blue;
          }
          
          .pagination-jump input {
              width: 60px;
              padding: 0.4rem;
              border: 1px solid #ced4da;
              border-radius: 4px;
              text-align: center;
              font-size: 0.9rem;
          }
          
          .pagination-jump button {
              background: #6c757d;
              color: white;
              border: none;
              padding: 0.4rem 0.6rem;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.8rem;
          }
          
          .pagination-jump button:hover {
              background: #5a6268;
          }

        .footer {
            font-size: 14px;
            color: #292929;
            margin: 15px auto;
            text-align: center;
        }
          
          /* 响应式设计 */
          @media (max-width: 768px) {
              .sites {
                  width: 100%;
                  margin: 0;
                  border-radius: 0;
              }
              
              .container {
                  margin: 0.5rem auto;
                  padding: 0 0.5rem;
              }
              
              .share-index {
                  padding: 0.5rem;
                  margin: 0;
              }
              
              .share-item {
                  flex-direction: column;
                  align-items: flex-start;
                  gap: 0.5rem;
                  padding: 0.5rem;
              }
              
              .share-item-info {
                  width: 100%;
                  overflow: hidden;
              }
              
              .share-item-title {
                  font-size: 0.9rem;
                  word-break: break-word;
                  overflow-wrap: break-word;
              }
              
              .share-item-preview {
                  font-size: 0.8rem;
                  -webkit-line-clamp: 3;
              }
              
              .share-item-date {
                  font-size: 0.7rem;
              }
              
              .share-item-actions {
                  margin-left: 0;
                  align-self: flex-end;
                  flex-shrink: 0;
              }
              
              .view-btn {
                  padding: 0.3rem 0.6rem;
                  font-size: 0.7rem;
              }
              
              .pagination {
                  flex-direction: column;
                  gap: 1rem;
                  padding: 0.5rem 0;
              }
              
              .pagination-info {
                  margin-right: 0;
                  margin-bottom: 0.5rem;
                  text-align: center;
                  font-size: 0.8rem;
              }
              
              .pagination-controls {
                  flex-wrap: wrap;
                  justify-content: center;
                  gap: 0.3rem;
              }
              
              .pagination-btn {
                  padding: 0.4rem 0.6rem;
                  font-size: 0.8rem;
                  min-width: 40px;
              }
              
              .pagination-current {
                  padding: 0.4rem 0.6rem;
                  font-size: 0.8rem;
                  min-width: 40px;
              }
              
              .pagination-jump {
                  margin-left: 0;
                  margin-top: 0.5rem;
                  flex-wrap: wrap;
                  justify-content: center;
                  gap: 0.3rem;
              }
              
              .pagination-jump input {
                  width: 50px;
                  padding: 0.3rem;
                  font-size: 0.8rem;
              }
              
              .pagination-jump button {
                  padding: 0.3rem 0.5rem;
                  font-size: 0.7rem;
              }
              
              .pagination-jump span {
                  font-size: 0.8rem;
              }
              
              /* 确保所有元素不会溢出 */
              * {
                  max-width: 100%;
                  box-sizing: border-box;
              }
              
              .share-item-title,
              .share-item-preview {
                  word-break: break-word;
                  overflow-wrap: break-word;
                  hyphens: auto;
              }
              
              .share-date-group {
                  margin-bottom: 1rem;
              }
              
              .date-header {
                  font-size: 0.8rem;
                  padding: 0.3rem 0.5rem;
              }
          }
      </style>
  </head>
  <body>
  <div class="sites">
       <div class="header">
           <div class="logo">WS01 Note - 分享目录</div>

       </div>
      
      <div class="container">
          <div class="share-index">
              <div class="share-index-header">
                  <h1 class="share-index-title">分享文章目录</h1>
                  <p class="share-index-subtitle">这里展示所有公开分享的文章,点击标题可查看完整内容。复制的分享内容可能有改变。</p>
              </div>
              
              <div id="shareList" class="share-list">
                  <div class="loading">加载中...</div>
              </div>
              
              <div id="pagination" class="pagination" style="display: none;">
                  <div class="pagination-info" id="paginationInfo"></div>
                  <div class="pagination-controls">
                      <button class="pagination-btn" id="prevBtn" onclick="changePage(currentPage - 1)">上一页</button>
                      <div id="pageNumbers"></div>
                      <button class="pagination-btn" id="nextBtn" onclick="changePage(currentPage + 1)">下一页</button>
                  </div>
                  <div class="pagination-jump">
                      <span>跳转到</span>
                      <input type="number" id="jumpInput" min="1" placeholder="">页
                      <button onclick="jumpToPage()">跳转</button>
                  </div>
              </div>
          </div>
      </div>

    <div class="footer">
        <span id="timeDate">载入天数...</span>
        <script language="javascript"> 
        var now = new Date();
        function createtime(){
            var grt= new Date("10/12/2025 00:00:00");/*---这里是网站的启用时间:月日年--*/
            now.setTime(now.getTime()+250);
            days = (now - grt ) / 1000 / 60 / 60 / 24;
            dnum = Math.floor(days);
            document.getElementById("timeDate").innerHTML = "稳定运行"+dnum+"天";
        }
        setInterval("createtime()",250); 
        </script> 

        <span <p>  | 本页总访问量 <span id="busuanzi_site_pv"></span> 次 | <a href="/" target="_blank">登录</p></span>
        <script defer src="https://bsz.211119.xyz/js"></script>
  
      <script>
          // 全局变量
          let currentPage = 1;
          let totalPages = 1;
          let totalCount = 0;
          const pageSize = 20;
          
          // 从URL获取当前页码
          function getCurrentPageFromUrl() {
              const urlParams = new URLSearchParams(window.location.search);
              return parseInt(urlParams.get('page')) || 1;
          }
          
          // 更新URL
          function updateUrl(page) {
              const url = new URL(window.location);
              if (page > 1) {
                  url.searchParams.set('page', page);
              } else {
                  url.searchParams.delete('page');
              }
              window.history.replaceState({}, '', url);
          }
          
          // 加载所有分享日记
          async function loadAllShares(page = 1) {
              try {
                  currentPage = page;
                  const response = await fetch(\`/api/shares?page=\${page}&limit=\${pageSize}\`);
                  
                  if (response.ok) {
                      const result = await response.json();
                      displayAllShares(result.shares);
                      updatePagination(result.pagination);
                      updateUrl(page);
                  } else {
                      showError('加载失败,请稍后重试');
                  }
              } catch (error) {
                  showError('网络错误,请重试');
              }
          }
          
          // 显示所有分享日记
          function displayAllShares(shares) {
              const shareList = document.getElementById('shareList');
              
              if (shares.length === 0) {
                  shareList.innerHTML = \`
                  <div class="empty-state">
                      <div class="empty-state-icon">📝</div>
                      <div>暂无分享日记</div>
                  </div>\`;
                  return;
              }
              
              // 按日期分组分享日记
              const groupedShares = {};
              shares.forEach(share => {
                  const date = new Date(share.date).toLocaleDateString('zh-CN');
                  if (!groupedShares[date]) {
                      groupedShares[date] = [];
                  }
                  groupedShares[date].push(share);
              });
              
              // 生成HTML
              let html = '';
              const sortedDates = Object.keys(groupedShares).sort((a, b) => new Date(b) - new Date(a));
              
              sortedDates.forEach(date => {
                  html += \`<div class="share-date-group">
                      <div class="date-header">\${date}</div>
                      <div class="share-items">\`;
                  
                  groupedShares[date].forEach(share => {
                      // 生成内容预览(前100个字符)
                      const preview = share.content.length > 100 
                          ? share.content.substring(0, 100) + '...' 
                          : share.content;
                      
                      html += \`<div class="share-item" onclick="viewShare('\${share.shareUrl}')">
                          <div class="share-item-info">
                              <div class="share-item-title">\${share.title}</div>
                              <div class="share-item-preview">\${preview}</div>
                              <div class="share-item-date">\${new Date(share.date).toLocaleString('zh-CN')}</div>
                          </div>
                          <div class="share-item-actions">
                              <a href="\${share.shareUrl}" class="view-btn" onclick="event.stopPropagation()">查看</a>
                          </div>
                      </div>\`;
                  });
  
                  html += \`</div></div>\`;
              });
              
              shareList.innerHTML = html;
          }
          
          // 查看分享日记
          function viewShare(shareUrl) {
              window.open(shareUrl, '_blank');
          }
          
          // 显示错误
          function showError(message) {
              const shareList = document.getElementById('shareList');
              shareList.innerHTML = \`<div class="error">\${message}</div>\`;
          }
          
          // 更新分页控件
          function updatePagination(pagination) {
              const paginationDiv = document.getElementById('pagination');
              const paginationInfo = document.getElementById('paginationInfo');
              const pageNumbers = document.getElementById('pageNumbers');
              const prevBtn = document.getElementById('prevBtn');
              const nextBtn = document.getElementById('nextBtn');
              
              currentPage = pagination.currentPage;
              totalPages = pagination.totalPages;
              totalCount = pagination.totalCount;
              
              // 更新分页信息
              const startItem = (currentPage - 1) * pageSize + 1;
              const endItem = Math.min(currentPage * pageSize, totalCount);
              paginationInfo.textContent = \`显示 \${startItem}-\${endItem} 条,共 \${totalCount} 条记录\`;
              
              // 更新按钮状态
              prevBtn.disabled = !pagination.hasPrev;
              nextBtn.disabled = !pagination.hasNext;
              
              // 生成页码按钮
              let pageHtml = '';
              const maxVisiblePages = 5;
              let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
              let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1);
              
              if (endPage - startPage + 1 < maxVisiblePages) {
                  startPage = Math.max(1, endPage - maxVisiblePages + 1);
              }
              
              if (startPage > 1) {
                  pageHtml += \`<button class="pagination-btn" onclick="changePage(1)">1</button>\`;
                  if (startPage > 2) {
                      pageHtml += \`<span style="padding: 0.5rem;">...</span>\`;
                  }
              }
              
              for (let i = startPage; i <= endPage; i++) {
                  if (i === currentPage) {
                      pageHtml += \`<button class="pagination-current">\${i}</button>\`;
                  } else {
                      pageHtml += \`<button class="pagination-btn" onclick="changePage(\${i})">\${i}</button>\`;
                  }
              }
              
              if (endPage < totalPages) {
                  if (endPage < totalPages - 1) {
                      pageHtml += \`<span style="padding: 0.5rem;">...</span>\`;
                  }
                  pageHtml += \`<button class="pagination-btn" onclick="changePage(\${totalPages})">\${totalPages}</button>\`;
              }
              
              pageNumbers.innerHTML = pageHtml;
              
              // 显示分页控件
              if (totalPages > 1) {
                  paginationDiv.style.display = 'flex';
              } else {
                  paginationDiv.style.display = 'none';
              }
          }
          
          // 切换页面
          function changePage(page) {
              if (page >= 1 && page <= totalPages && page !== currentPage) {
                  loadAllShares(page);
                  // 滚动到顶部
                  window.scrollTo({ top: 0, behavior: 'smooth' });
              }
          }
          
          // 跳转到指定页面
          function jumpToPage() {
              const jumpInput = document.getElementById('jumpInput');
              const page = parseInt(jumpInput.value);
              
              if (page >= 1 && page <= totalPages) {
                  changePage(page);
                  jumpInput.value = '';
              } else {
                  alert(\`请输入 1 到 \${totalPages} 之间的页码\`);
              }
          }
          
          // 页面加载时加载所有分享日记
          loadAllShares(getCurrentPageFromUrl());
      </script>
  </body>
  </html>`;
  }
  
  // 分享页面
  function getSharePage(shareId) {
    return `
  <!DOCTYPE html>
  <html lang="zh-CN">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>WS01 Note - 分享内容</title>
      <style>
          * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
          }
          
          body {
              font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
              background: #f8f9fa;
              min-height: 100vh;
          }
          
          .sites {
              width: 1000px;
              background: #F2F2F2;
              border: 1px solid rgba(0,0,0,.06);
              margin: 10px auto;
              padding: 0px;
              color: white;
              border-radius: 6px;
          }
          
          .header {
              background: #D4D4D4;
              padding: 0.8rem 1.5rem;
              box-shadow: 0 1px 6px rgba(0,0,0,0.08);
              display: flex;
              justify-content: center;
              align-items: center;
              position: relative;
          }
          
          .logo {
              font-size: 1.5rem;
              font-weight: 400;
              color: #333;
          }
          
          .back-btn {
              background: #1C86EE;
              color: white;
              border: none;
              padding: 0.4rem 0.8rem;
              border-radius: 4px;
              cursor: pointer;
              font-size: 0.8rem;
              position: absolute;
              right: 2.6rem;
              text-decoration: none;
              display: inline-block;
          }
          
          .back-btn:hover {
              background: #1874CD;
          }
          
          .container {
              max-width: 960px;
              margin: 1.5rem auto;
              padding: 0 1.5rem;
          }
          
          .diary-detail {
              background: white;
              padding: 1.5rem;
              border-radius: 8px;
              box-shadow: 0 2px 12px rgba(0,0,0,0.08);
              max-height: 900px;
              overflow-y: auto;
          }
          
          .diary-header {
              border-bottom: 1px solid #e9ecef;
              padding-bottom: 0.8rem;
              margin-bottom: 1.2rem;
          }
          
          .diary-title {
              font-size: 1.5rem;
              color: #333;
              margin-bottom: 0.4rem;
              font-weight: 600;
              word-wrap: break-word;
          }
          
          .diary-date {
              color: #666;
              font-size: 0.8rem;
          }
          
          .diary-content {
              color: #333;
              line-height: 1.6;
              white-space: pre-wrap;
              font-size: 0.9rem;
              word-wrap: break-word;
              overflow-wrap: break-word;
              word-break: break-all;
              border: 1px dashed #ccc;
              padding: 0.8rem;
              border-radius: 4px;
          }
          
          .loading {
              text-align: center;
              padding: 2rem;
              color: #666;
          }
          
          .error {
              text-align: center;
              padding: 2rem;
              color: #e74c3c;
          }
          
          .share-notice {
              background: #e7f3ff;
              border: 1px solid #b3d9ff;
              border-radius: 4px;
              padding: 0.8rem;
              margin-bottom: 1rem;
              color: #0066cc;
              font-size: 0.9rem;
          }
          
          .notification {
              position: fixed;
              top: 15px;
              right: 15px;
              background: #28a745;
              color: white;
              padding: 0.8rem;
              border-radius: 4px;
              box-shadow: 0 2px 8px rgba(0,0,0,0.12);
              display: none;
              z-index: 1000;
              font-size: 0.9rem;
              max-width: 300px;
          }

        .footer {
            font-size: 14px;
            color: #292929;
            margin: 15px auto;
            text-align: center;
        }
          
          /* 响应式设计 */
          @media (max-width: 768px) {
              .sites {
                  width: 95%;
                  margin: 5px auto;
              }
              
              .container {
                  margin: 1rem auto;
                  padding: 0 1rem;
              }
              
              .diary-detail {
                  padding: 1rem;
              }
          }
      </style>
  </head>
  <body>
  <div class="sites">
       <div class="header">
           <div class="logo">WS01 Note - 分享内容</div>
           <a href="/share" class="back-btn">← 返回分享目录</a>
       </div>
      
      <div class="container">
          <div class="share-notice">
              📢 这是一篇分享的文章,任何人都可以查看
          </div>
          
          <div id="diaryDetail" class="diary-detail">
              <div class="loading">加载中...</div>
          </div>
          
          <!-- 通知元素 -->
          <div id="notification" class="notification">内容已复制到剪贴板</div>
      </div>

    <div class="footer">
        <span id="timeDate">载入天数...</span>
        <script language="javascript"> 
        var now = new Date();
        function createtime(){
            var grt= new Date("10/12/2025 00:00:00");/*---这里是网站的启用时间:月日年--*/
            now.setTime(now.getTime()+250);
            days = (now - grt ) / 1000 / 60 / 60 / 24;
            dnum = Math.floor(days);
            document.getElementById("timeDate").innerHTML = "稳定运行"+dnum+"天";
        }
        setInterval("createtime()",250); 
        </script> 

        <span <p>  | 本页总访问量 <span id="busuanzi_site_pv"></span> 次 | <a href="/" target="_blank">登录</p></span>
        <script defer src="https://bsz.211119.xyz/js"></script>
  
      <script>
          const shareId = '${shareId}';
          
          // 加载分享日记
          async function loadSharedDiary() {
              try {
                  const response = await fetch(\`/api/share/\${shareId}\`);
                  
                  if (response.ok) {
                      const diary = await response.json();
                      displaySharedDiary(diary);
                  } else if (response.status === 404) {
                      showError('分享的日记不存在或已被删除');
                  } else {
                      showError('加载失败,请稍后重试');
                  }
              } catch (error) {
                  showError('网络错误,请重试');
              }
          }
          
          // 显示分享日记
          function displaySharedDiary(diary) {
              const diaryDetail = document.getElementById('diaryDetail');
              const date = new Date(diary.date).toLocaleString('zh-CN');
              
              diaryDetail.innerHTML = \`
                  <div class="diary-header">
                      <div class="title-container">
                          <h1 class="diary-title">\${diary.title}</h1>
                          <button class="copy-btn" onclick="copyShareContent()">复制内容</button>
                      </div>
                      <div class="diary-date">\${date}</div>
                  </div>
                  <div class="diary-content" id="shareContent"></div>
              \`;
              
              // 使用textContent设置内容,避免HTML标签被解析
              document.getElementById('shareContent').textContent = diary.content;
              
              // 将原始内容存储到全局变量中,供复制功能使用
              window.shareContent = diary.content;
          }
          
          // 显示错误
          function showError(message) {
              const diaryDetail = document.getElementById('diaryDetail');
              diaryDetail.innerHTML = \`<div class="error">\${message}</div>\`;
          }
          
          // 复制内容功能
          function copyContent(content) {
              navigator.clipboard.writeText(content).then(() => {
                  const notification = document.getElementById('notification');
                  notification.style.display = 'block';
                  
                  setTimeout(() => {
                      notification.style.display = 'none';
                  }, 3000);
              }).catch(err => {
                  console.error('复制失败:', err);
                  const notification = document.getElementById('notification');
                  notification.textContent = '复制失败';
                  notification.style.backgroundColor = '#dc3545';
                  notification.style.display = 'block';
                  
                  setTimeout(() => {
                      notification.style.display = 'none';
                      // 恢复默认文本和颜色
                      notification.textContent = '内容已复制到剪贴板';
                      notification.style.backgroundColor = '#28a745';
                  }, 3000);
              });
          }
          
          // 复制分享内容功能
          function copyShareContent() {
              if (window.shareContent) {
                  copyContent(window.shareContent);
              } else {
                  // 如果全局变量不存在,尝试从DOM元素获取
                  const contentElement = document.getElementById('shareContent');
                  if (contentElement) {
                      copyContent(contentElement.textContent);
                  } else {
                      console.error('无法获取分享内容');
                      const notification = document.getElementById('notification');
                      notification.textContent = '复制失败:无法获取内容';
                      notification.style.backgroundColor = '#dc3545';
                      notification.style.display = 'block';
                      
                      setTimeout(() => {
                          notification.style.display = 'none';
                      }, 3000);
                  }
              }
          }
          
          // 页面加载时加载分享日记
          loadSharedDiary();
      </script>
  </body>
  </html>`;
  }
  
  // 处理认证API
  async function handleAuth(request, env, corsHeaders) {
    if (request.method !== 'POST') {
      return new Response('方法不允许', { 
        status: 405, 
        headers: { 'Content-Type': 'text/plain; charset=utf-8', ...corsHeaders }
      });
    }
  
    try {
      const { username, password } = await request.json();
      
      // 验证用户名和密码(从环境变量获取)
      const validUsername = env.USERNAME || '9527a';
      const validPassword = env.PASSWORD || '9527abc';
      
      if (username === validUsername && password === validPassword) {
        // 生成简单的token(实际应用中应该使用更安全的方法)
        const token = btoa(username + ':' + Date.now());
        
        return new Response(JSON.stringify({
          success: true,
          token: token,
          message: '登录成功'
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      } else {
        return new Response(JSON.stringify({
          success: false,
          message: '用户名或密码错误'
        }), {
          status: 401,
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
    } catch (error) {
      return new Response(JSON.stringify({
        success: false,
        message: '请求格式错误'
      }), {
        status: 400,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }
  
  // 处理日记API
  async function handleDiaryAPI(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  
    const token = authHeader.substring(7);
    
    try {
      if (request.method === 'GET') {
        // 获取日记列表
        const diaries = await getDiaries(env);
        return new Response(JSON.stringify({
          success: true,
          diaries: diaries
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
      
      if (request.method === 'POST') {
        // 保存新日记
        const { title, content, editShareId } = await request.json();
        const diary = {
          id: Date.now().toString(),
          title: title,
          content: content,
          date: new Date().toISOString()
        };
        
        await saveDiary(env, diary);
        
        // 如果是从分享日记编辑而来,需要从分享日记中删除
        if (editShareId) {
          await env.WS01_NOTE_KV.delete(`shared_${editShareId}`);
        }
        
        return new Response(JSON.stringify({
          success: true,
          message: '日记保存成功'
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
      
      // 添加: 处理更新日记 (PUT)
      if (request.method === 'PUT') {
        const { id, title, content } = await request.json();
        
        // 获取现有日记
        const diaries = await getDiaries(env);
        const diaryIndex = diaries.findIndex(d => d.id === id);
        
        if (diaryIndex === -1) {
          return new Response(JSON.stringify({
            success: false,
            message: '日记不存在'
          }), {
            status: 404,
            headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
          });
        }
        
        // 更新日记内容
        diaries[diaryIndex] = {
          ...diaries[diaryIndex],
          title,
          content,
          date: new Date().toISOString() // 更新时间
        };
        
        await env.WS01_NOTE_KV.put('diaries', JSON.stringify(diaries));
        
        return new Response(JSON.stringify({
          success: true,
          message: '日记更新成功'
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
      
      // 添加: 处理删除日记 (DELETE)
      if (request.method === 'DELETE') {
        const { id } = await request.json();
        const diaries = await getDiaries(env);
        const filteredDiaries = diaries.filter(d => d.id !== id);
        
        if (filteredDiaries.length === diaries.length) {
          return new Response(JSON.stringify({
            success: false,
            message: '日记不存在'
          }), {
            status: 404,
            headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
          });
        }
        
        await env.WS01_NOTE_KV.put('diaries', JSON.stringify(filteredDiaries));
        
        return new Response(JSON.stringify({
          success: true,
          message: '日记删除成功'
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
  
      return new Response('方法不允许', { 
        status: 405, 
        headers: { 'Content-Type': 'text/plain; charset=utf-8', ...corsHeaders }
      });
      
    } catch (error) {
      console.error('日记API错误:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }
  
  // 获取日记列表
  async function getDiaries(env) {
    try {
      const diariesJson = await env.WS01_NOTE_KV.get('diaries');
      if (diariesJson) {
        const diaries = JSON.parse(diariesJson);
        return diaries.sort((a, b) => new Date(b.date) - new Date(a.date));
      }
      return [];
    } catch (error) {
      console.error('获取日记失败:', error);
      return [];
    }
  }
  
  // 保存日记
  async function saveDiary(env, diary) {
    try {
      const diaries = await getDiaries(env);
      diaries.unshift(diary); // 添加到开头
      
      // 限制最多保存100篇日记
      if (diaries.length > 100) {
        diaries.splice(100);
      }
      
      await env.WS01_NOTE_KV.put('diaries', JSON.stringify(diaries));
    } catch (error) {
      console.error('保存日记失败:', error);
      throw error;
    }
  }
  
  // 处理创建备份
  async function handleCreateBackup(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  
    try {
      // 获取当前所有日记
      const diaries = await getDiaries(env);
      
      // 获取所有分享日记
      const listResult = await env.WS01_NOTE_KV.list({ prefix: 'shared_' });
      const shares = [];
      for (const key of listResult.keys) {
        try {
          const sharedDiaryJson = await env.WS01_NOTE_KV.get(key.name);
          if (sharedDiaryJson) {
            const sharedDiary = JSON.parse(sharedDiaryJson);
            shares.push(sharedDiary);
          }
        } catch (e) {
          console.error('读取分享日记失败:', e);
        }
      }
      
      // 创建备份数据
      const backup = {
        id: Date.now().toString(),
        timestamp: new Date().toISOString(),
        data: diaries,
        shares: shares,
        count: diaries.length,
        shareCount: shares.length
      };
      
      // 获取现有的备份列表
      let backups = [];
      try {
        const backupsJson = await env.WS01_NOTE_KV.get('backups');
        if (backupsJson) {
          backups = JSON.parse(backupsJson);
        }
      } catch (e) {
        console.error('读取备份列表失败:', e);
      }
      
      // 添加新备份到列表开头
      backups.unshift(backup);
      
      // 限制最多5个备份
      if (backups.length > 5) {
        backups = backups.slice(0, 5);
      }
      
      // 保存备份列表
      await env.WS01_NOTE_KV.put('backups', JSON.stringify(backups));
      
      return new Response(JSON.stringify({
        success: true,
        message: '备份创建成功',
        backupId: backup.id
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('创建备份失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }
  
  // 处理获取备份列表
  async function handleGetBackups(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  
    try {
      // 获取备份列表
      let backups = [];
      try {
        const backupsJson = await env.WS01_NOTE_KV.get('backups');
        if (backupsJson) {
          backups = JSON.parse(backupsJson);
        }
      } catch (e) {
        console.error('读取备份列表失败:', e);
      }
      
      // 只返回必要的信息
      const backupInfo = backups.map(backup => ({
        id: backup.id,
        timestamp: backup.timestamp,
        count: backup.count,
        shareCount: backup.shareCount || 0
      }));
      
      return new Response(JSON.stringify({
        success: true,
        backups: backupInfo
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('获取备份列表失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }
  
  // 处理恢复备份
  async function handleRestoreBackup(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  
    try {
      const { backupId } = await request.json();
      
      // 获取备份列表
      let backups = [];
      try {
        const backupsJson = await env.WS01_NOTE_KV.get('backups');
        if (backupsJson) {
          backups = JSON.parse(backupsJson);
        }
      } catch (e) {
        console.error('读取备份列表失败:', e);
      }
      
      // 查找指定的备份
      const backup = backups.find(b => b.id === backupId);
      if (!backup) {
        return new Response(JSON.stringify({
          success: false,
          message: '备份不存在'
        }), {
          status: 404,
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
      
      // 恢复个人日记数据
      await env.WS01_NOTE_KV.put('diaries', JSON.stringify(backup.data));
      
      // 恢复分享日记数据
      if (backup.shares && backup.shares.length > 0) {
        // 先删除所有现有的分享日记
        const existingShares = await env.WS01_NOTE_KV.list({ prefix: 'shared_' });
        for (const key of existingShares.keys) {
          await env.WS01_NOTE_KV.delete(key.name);
        }
        
        // 恢复备份中的分享日记
        for (const share of backup.shares) {
          await env.WS01_NOTE_KV.put(`shared_${share.id}`, JSON.stringify(share));
        }
      }
      
      return new Response(JSON.stringify({
        success: true,
        message: '数据恢复成功'
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('恢复备份失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }
  
  // 处理分享日记
  async function handleShareDiary(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }

    try {
      const { title, content, shareId, editDiaryId } = await request.json();
      
      if (request.method === 'PUT' && shareId) {
        // 更新分享日记
        const existingShareJson = await env.WS01_NOTE_KV.get(`shared_${shareId}`);
        if (!existingShareJson) {
          return new Response(JSON.stringify({
            success: false,
            message: '分享日记不存在'
          }), {
            status: 404,
            headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
          });
        }
        
        const existingShare = JSON.parse(existingShareJson);
        const updatedShare = {
          ...existingShare,
          title: title,
          content: content,
          date: new Date().toISOString() // 更新修改时间
        };
        
        await env.WS01_NOTE_KV.put(`shared_${shareId}`, JSON.stringify(updatedShare));
        
        return new Response(JSON.stringify({
          success: true,
          message: '分享日记更新成功',
          shareId: shareId
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      } else {
        // 创建新分享日记
        const newShareId = Date.now().toString() + Math.random().toString(36).substr(2, 9);
        const sharedDiary = {
          id: newShareId,
          title: title,
          content: content,
          date: new Date().toISOString(),
          shared: true
        };
        
        // 保存到KV存储
        await env.WS01_NOTE_KV.put(`shared_${newShareId}`, JSON.stringify(sharedDiary));
        
        // 如果是从我的日记编辑而来,需要从我的日记中删除
        if (editDiaryId) {
          const diaries = await getDiaries(env);
          const filteredDiaries = diaries.filter(d => d.id !== editDiaryId);
          await env.WS01_NOTE_KV.put('diaries', JSON.stringify(filteredDiaries));
        }
        
        return new Response(JSON.stringify({
          success: true,
          message: '分享成功',
          shareId: newShareId
        }), {
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
    } catch (error) {
      console.error('分享日记失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }

  // 处理获取分享日记
  async function handleGetSharedDiary(shareId, env, corsHeaders) {
    try {
      // 从KV存储中获取分享日记
      const sharedDiaryJson = await env.WS01_NOTE_KV.get(`shared_${shareId}`);
      
      if (!sharedDiaryJson) {
        return new Response(JSON.stringify({
          success: false,
          message: '分享的日记不存在'
        }), {
          status: 404,
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
      
      const sharedDiary = JSON.parse(sharedDiaryJson);
      
      return new Response(JSON.stringify(sharedDiary), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('获取分享日记失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }

  // 处理获取所有分享日记(公开访问)
  async function handleGetAllShares(request, env, corsHeaders) {
    try {
      // 解析URL参数
      const url = new URL(request.url);
      const page = parseInt(url.searchParams.get('page')) || 1;
      const limit = parseInt(url.searchParams.get('limit')) || 20;
      
      // 获取所有分享日记的键
      const listResult = await env.WS01_NOTE_KV.list({ prefix: 'shared_' });
      
      const shares = [];
      for (const key of listResult.keys) {
        try {
          const sharedDiaryJson = await env.WS01_NOTE_KV.get(key.name);
          if (sharedDiaryJson) {
            const sharedDiary = JSON.parse(sharedDiaryJson);
            shares.push({
              id: sharedDiary.id,
              title: sharedDiary.title,
              content: sharedDiary.content,
              date: sharedDiary.date,
              shareUrl: `/share/${sharedDiary.id}`
            });
          }
        } catch (e) {
          console.error('解析分享日记失败:', e);
        }
      }
      
      // 按日期排序(最新的在前)
      shares.sort((a, b) => new Date(b.date) - new Date(a.date));
      
      // 计算分页
      const totalCount = shares.length;
      const totalPages = Math.ceil(totalCount / limit);
      const startIndex = (page - 1) * limit;
      const endIndex = startIndex + limit;
      const paginatedShares = shares.slice(startIndex, endIndex);
      
      return new Response(JSON.stringify({
        success: true,
        shares: paginatedShares,
        pagination: {
          currentPage: page,
          totalPages: totalPages,
          totalCount: totalCount,
          limit: limit,
          hasNext: page < totalPages,
          hasPrev: page > 1
        }
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('获取所有分享日记失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }

  // 处理获取用户分享日记列表
  async function handleGetUserShares(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }

    try {
      // 获取所有分享日记的键
      const listResult = await env.WS01_NOTE_KV.list({ prefix: 'shared_' });
      
      const shares = [];
      for (const key of listResult.keys) {
        try {
          const sharedDiaryJson = await env.WS01_NOTE_KV.get(key.name);
          if (sharedDiaryJson) {
            const sharedDiary = JSON.parse(sharedDiaryJson);
            shares.push({
              id: sharedDiary.id,
              title: sharedDiary.title,
              content: sharedDiary.content,
              date: sharedDiary.date,
              shareUrl: `${request.url.split('/')[0]}//${request.headers.get('host')}/share/${sharedDiary.id}`
            });
          }
        } catch (e) {
          console.error('解析分享日记失败:', e);
        }
      }
      
      // 按日期排序(最新的在前)
      shares.sort((a, b) => new Date(b.date) - new Date(a.date));
      
      return new Response(JSON.stringify({
        success: true,
        shares: shares
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('获取分享日记列表失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }

  // 处理删除分享日记
  async function handleDeleteShare(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }

    try {
      const { shareId } = await request.json();
      
      // 删除分享日记
      await env.WS01_NOTE_KV.delete(`shared_${shareId}`);
      
      return new Response(JSON.stringify({
        success: true,
        message: '分享日记删除成功'
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('删除分享日记失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }

  // 处理删除备份
  async function handleDeleteBackup(request, env, corsHeaders) {
    // 验证token
    const authHeader = request.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return new Response(JSON.stringify({
        success: false,
        message: '未授权'
      }), {
        status: 401,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  
    try {
      const { backupId } = await request.json();
      
      // 获取备份列表
      let backups = [];
      try {
        const backupsJson = await env.WS01_NOTE_KV.get('backups');
        if (backupsJson) {
          backups = JSON.parse(backupsJson);
        }
      } catch (e) {
        console.error('读取备份列表失败:', e);
      }
      
      // 过滤掉要删除的备份
      const filteredBackups = backups.filter(b => b.id !== backupId);
      
      if (filteredBackups.length === backups.length) {
        return new Response(JSON.stringify({
          success: false,
          message: '备份不存在'
        }), {
          status: 404,
          headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
        });
      }
      
      // 保存更新后的备份列表
      await env.WS01_NOTE_KV.put('backups', JSON.stringify(filteredBackups));
      
      return new Response(JSON.stringify({
        success: true,
        message: '备份删除成功'
      }), {
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    } catch (error) {
      console.error('删除备份失败:', error);
      return new Response(JSON.stringify({
        success: false,
        message: '服务器错误'
      }), {
        status: 500,
        headers: { 'Content-Type': 'application/json; charset=utf-8', ...corsHeaders }
      });
    }
  }
0

评论 (0)

取消