Files
outlookEmailPlus/templates/index.html
T
胡绍康andClaude Opus 4.6 0ab50db85f feat: 实现可调整布局系统
- 新增布局管理器支持拖拽调整面板宽度
- 新增状态管理器实现布局持久化
- 重构前端页面结构优化四栏式布局
- 新增 Jest 测试框架和完整测试用例
- 完善项目文档(PRD/FD/TDD/TODO/LOG)
- 清理 Python 缓存文件并更新 .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:49:36 +08:00

233 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Outlook 邮件管理</title>
<!-- DOMPurify for XSS protection -->
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.8/dist/purify.min.js"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
<!-- 可调整布局系统:需在 main.css 之后引入以覆盖旧布局样式 -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/layout.css') }}">
</head>
<body>
<!-- 顶部导航栏 -->
<nav class="navbar">
<div class="navbar-brand">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
<polyline points="22,6 12,13 2,6"></polyline>
</svg>
Outlook 邮件
<a href="https://github.com/assast/outlookEmail" target="_blank" class="github-star-btn"
style="margin-left: 16px;">
<svg viewBox="0 0 16 16" fill="currentColor">
<path
d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z" />
</svg>
Star on GitHub
</a>
</div>
<div class="navbar-center">
<div class="current-account" id="currentAccount" onclick="copyCurrentEmail()" title="点击复制邮箱地址">
当前邮箱:<strong id="currentAccountEmail"></strong>
</div>
</div>
<div class="navbar-actions">
<button class="navbar-btn" onclick="showRefreshModal()">全量刷新Token</button>
<button class="navbar-btn" onclick="showExportModal()">导出邮箱</button>
<button class="navbar-btn" onclick="showSettingsModal()">⚙️ 设置</button>
<button class="navbar-btn reset-layout-btn" onclick="showResetLayoutModal()"
aria-label="恢复默认布局" title="恢复默认布局">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polyline points="1 4 1 10 7 10"></polyline>
<path d="M3.51 15a9 9 0 102.13-9.36L1 10"></path>
</svg>
</button>
<button class="navbar-btn" onclick="logout()" style="color: #dc3545;">退出登录</button>
</div>
</nav>
<!-- 主容器 -->
<div class="main-container">
<!-- 分组面板 -->
<div class="group-panel resizable-panel" id="groupPanel" data-panel="groups">
<div class="panel-header">
<span class="panel-title">分组</span>
<div style="display: flex; align-items: center; gap: 4px;">
<button class="panel-action-btn" onclick="showAddGroupModal()" title="添加分组">+</button>
<button class="panel-action-btn collapse-btn" data-panel="groups" aria-label="折叠分组面板"
aria-expanded="true" title="折叠分组面板">
←
</button>
</div>
</div>
<div class="group-list" id="groupList">
<!-- 分组列表将通过 JS 动态加载 -->
</div>
<div class="resizer" role="separator" aria-orientation="vertical" aria-label="调整分组面板宽度"
aria-valuenow="200" aria-valuemin="150" aria-valuemax="400" tabindex="0" data-resizer="groups">
</div>
</div>
<!-- 邮箱账号面板 -->
<div class="account-panel resizable-panel" id="accountPanel" data-panel="accounts">
<div class="account-panel-header">
<div class="account-panel-title" id="accountPanelTitle">
<span class="group-color" id="currentGroupColor" style="background-color: #666"></span>
<span id="currentGroupName">选择分组</span>
</div>
<div style="margin-left: auto;">
<button class="panel-action-btn" onclick="showTagManagementModal()" title="管理标签">
🏷️
</button>
<button class="panel-action-btn" onclick="showAddAccountModal()" title="导入账号">
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
<path fill-rule="evenodd"
d="M8 2a.75.75 0 01.75.75v4.5h4.5a.75.75 0 010 1.5h-4.5v4.5a.75.75 0 01-1.5 0v-4.5h-4.5a.75.75 0 010-1.5h4.5v-4.5A.75.75 0 018 2z" />
</svg>
</button>
<button class="panel-action-btn collapse-btn" data-panel="accounts" aria-label="折叠账号面板"
aria-expanded="true" title="折叠账号面板">
←
</button>
</div>
</div>
<div class="search-container">
<input type="text" id="globalSearch" class="search-input" placeholder="搜索邮箱地址..." autocomplete="off">
</div>
<div class="sort-control"
style="padding: 8px 16px; border-bottom: 1px solid #e5e5e5; display: flex; align-items: center; gap: 8px; background-color: #fafafa;">
<label style="font-size: 12px; color: #666; font-weight: 500;">排序:</label>
<div style="display: flex; gap: 4px;">
<button class="sort-btn active" data-sort="refresh_time" onclick="sortAccounts('refresh_time')"
style="padding: 4px 10px; font-size: 12px; background-color: #1a1a1a; border: 1px solid #1a1a1a; border-radius: 4px; color: #ffffff; cursor: pointer; transition: all 0.15s;">
🕐 刷新时间
</button>
<button class="sort-btn" data-sort="email" onclick="sortAccounts('email')"
style="padding: 4px 10px; font-size: 12px; background-color: #ffffff; border: 1px solid #e5e5e5; border-radius: 4px; color: #666; cursor: pointer; transition: all 0.15s;">
📧 邮箱名
</button>
</div>
<!-- 全选复选框 -->
<div style="display: flex; align-items: center; gap: 4px; margin-left: auto;">
<input type="checkbox" id="selectAllCheckbox" onclick="toggleSelectAll()"
style="width: 14px; height: 14px; cursor: pointer;">
<label for="selectAllCheckbox" style="font-size: 12px; color: #666; cursor: pointer;">全选</label>
</div>
</div>
<!-- Tag Filter Row -->
<div id="tagFilterContainer"
style="padding: 8px 16px; border-bottom: 1px solid #e5e5e5; display: flex; flex-wrap: wrap; gap: 8px; background-color: #fafafa; display: none;">
<!-- Tags checkboxes will be rendered here -->
</div>
<div class="account-list" id="accountList">
<div class="empty-state">
<div class="empty-state-icon">📁</div>
<div class="empty-state-text">请从左侧选择一个分组</div>
</div>
</div>
<!-- 批量操作栏 -->
<div id="batchActionBar"
style="display: none; padding: 8px 16px; border-top: 1px solid #e5e5e5; background: #f8f9fa; gap: 8px; align-items: center;">
<span id="selectedCount" style="font-size: 12px; color: #666;">已选 0 项</span>
<div style="flex: 1;"></div>
<button class="btn btn-sm btn-secondary" onclick="showBatchTagModal('add')">打标签</button>
<button class="btn btn-sm btn-secondary" onclick="showBatchTagModal('remove')">去标签</button>
<button class="btn btn-sm btn-secondary" onclick="showBatchMoveGroupModal()">移动分组</button>
<button class="btn btn-sm btn-danger" onclick="showBatchDeleteConfirm()" style="background-color: #dc3545; border-color: #dc3545; color: white;">删除</button>
</div>
<div class="account-panel-footer">
<button class="add-account-btn" onclick="showAddAccountModal()">+ 导入邮箱</button>
</div>
<div class="resizer" role="separator" aria-orientation="vertical" aria-label="调整账号面板宽度"
aria-valuenow="260" aria-valuemin="180" aria-valuemax="500" tabindex="0" data-resizer="accounts">
</div>
</div>
<!-- 邮件列表面板 -->
<div class="email-list-panel resizable-panel" id="emailListPanel" data-panel="emails">
<div class="email-list-header">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;">
<div class="folder-tabs" id="folderTabs" style="display: none;">
<button class="folder-tab active" data-folder="inbox" onclick="switchFolder('inbox')">
📨 收件箱
</button>
<button class="folder-tab" data-folder="junkemail" onclick="switchFolder('junkemail')">
⚠️ 垃圾邮件
</button>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<button class="refresh-btn" onclick="refreshEmails()">获取邮件</button>
<button class="panel-action-btn collapse-btn" data-panel="emails" aria-label="折叠邮件列表面板"
aria-expanded="true" title="折叠邮件列表面板">
←
</button>
</div>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<h2 style="margin: 0; font-size: 16px; font-weight: 600;">
邮件
<span class="email-count" id="emailCount"></span>
</h2>
<span class="method-tag" id="methodTag" style="display:none;"></span>
</div>
</div>
<div class="email-list" id="emailList">
<div class="empty-state">
<div class="empty-state-icon">📬</div>
<div class="empty-state-text">请从左侧选择一个邮箱账号</div>
</div>
</div>
<!-- Email Batch Action Bar -->
<div id="emailBatchActionBar"
style="display: none; padding: 8px 16px; border-top: 1px solid #e5e5e5; background: #f8f9fa; gap: 8px; align-items: center;">
<span id="emailSelectedCount" style="font-size: 12px; color: #666;">已选 0 项</span>
<div style="flex: 1;"></div>
<button class="batch-btn danger" onclick="confirmBatchDeleteEmails()">
🗑️ 删除
</button>
</div>
<div class="resizer" role="separator" aria-orientation="vertical" aria-label="调整邮件列表面板宽度"
aria-valuenow="380" aria-valuemin="280" aria-valuemax="600" tabindex="0" data-resizer="emails">
</div>
</div>
<!-- 邮件详情面板(不可折叠) -->
<div class="email-detail-panel">
<div class="email-detail-toolbar" id="emailDetailToolbar" style="display:none;">
<button class="back-btn" onclick="showEmailList()">← 返回</button>
<button class="toggle-list-btn" onclick="toggleEmailList()">
<span id="toggleListText">隐藏列表</span>
</button>
<button class="fullscreen-btn" onclick="openFullscreenEmail()">🔍 全屏查看</button>
<label
style="display: flex; align-items: center; gap: 6px; font-size: 13px; margin-left: 12px; cursor: pointer;">
<input type="checkbox" id="trustEmailCheckbox" onchange="toggleTrustMode(this)">
<span style="user-select: none;">信任此邮件</span>
</label>
<div style="flex: 1;"></div>
<button class="batch-btn danger" onclick="confirmDeleteCurrentEmail()"
style="padding: 4px 8px; font-size: 12px;">
🗑️ 删除
</button>
</div>
<div id="emailDetail">
<div class="empty-state">
<div class="empty-state-icon">📄</div>
<div class="empty-state-text">选择一封邮件查看详情</div>
</div>
</div>
</div>
</div>
{% include 'partials/modals.html' %}
{% include 'partials/scripts.html' %}
</body>
</html>