165 lines
6.3 KiB
HTML
165 lines
6.3 KiB
HTML
|
|
<!doctype html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="utf-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|||
|
|
<title>邮件发送控制台</title>
|
|||
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/email_console.css') }}">
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="bg-glow glow-a"></div>
|
|||
|
|
<div class="bg-glow glow-b"></div>
|
|||
|
|
|
|||
|
|
<main class="container">
|
|||
|
|
<header class="hero">
|
|||
|
|
<p class="eyebrow">Traffic News Automation</p>
|
|||
|
|
<h1>邮件发送控制台</h1>
|
|||
|
|
<p class="subtitle">管理收件人、启动定时任务、执行单次发送</p>
|
|||
|
|
<div class="status-row">
|
|||
|
|
<span class="chip">发件账号: {{ sender_masked }}</span>
|
|||
|
|
{% if sender_ready %}
|
|||
|
|
<span class="chip chip-ok">状态: 可发送</span>
|
|||
|
|
{% else %}
|
|||
|
|
<span class="chip chip-warn">状态: 配置不完整</span>
|
|||
|
|
{% endif %}
|
|||
|
|
{% if scheduler_started %}
|
|||
|
|
<span class="chip chip-ok">定时任务: 运行中</span>
|
|||
|
|
{% else %}
|
|||
|
|
<span class="chip chip-warn">定时任务: 未启动</span>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|||
|
|
{% if messages %}
|
|||
|
|
<section class="messages">
|
|||
|
|
{% for category, message in messages %}
|
|||
|
|
<div class="msg msg-{{ category }}">{{ message }}</div>
|
|||
|
|
{% endfor %}
|
|||
|
|
</section>
|
|||
|
|
{% endif %}
|
|||
|
|
{% endwith %}
|
|||
|
|
|
|||
|
|
<section class="panel">
|
|||
|
|
<h2 class="section-title">发送对象管理</h2>
|
|||
|
|
<form method="post" action="{{ url_for('add_recipient') }}" class="recipient-add-form">
|
|||
|
|
<label for="new_recipient">新增目标邮箱</label>
|
|||
|
|
<div class="add-row">
|
|||
|
|
<input
|
|||
|
|
type="email"
|
|||
|
|
id="new_recipient"
|
|||
|
|
name="new_recipient"
|
|||
|
|
placeholder="例如: someone@qq.com"
|
|||
|
|
required
|
|||
|
|
>
|
|||
|
|
<button type="submit" class="btn-secondary">新增</button>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
|
|||
|
|
<div class="managed-list">
|
|||
|
|
{% if managed_recipients %}
|
|||
|
|
{% for recipient in managed_recipients %}
|
|||
|
|
<div class="managed-item">
|
|||
|
|
<span>{{ recipient }}</span>
|
|||
|
|
<form method="post" action="{{ url_for('delete_recipient') }}">
|
|||
|
|
<input type="hidden" name="email" value="{{ recipient }}">
|
|||
|
|
<button type="submit" class="btn-danger" onclick="return confirm('确认删除该邮箱吗?');">删除</button>
|
|||
|
|
</form>
|
|||
|
|
</div>
|
|||
|
|
{% endfor %}
|
|||
|
|
{% else %}
|
|||
|
|
<p class="hint">当前还没有发送对象,请先新增至少一个邮箱地址。</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<section class="panel">
|
|||
|
|
<h2 class="section-title">每周定时发送</h2>
|
|||
|
|
<form method="post" action="{{ url_for('update_schedule') }}" id="scheduleForm">
|
|||
|
|
<div class="block schedule-enable-row">
|
|||
|
|
<label class="switch-row" for="schedule_enabled">
|
|||
|
|
<input type="checkbox" id="schedule_enabled" name="schedule_enabled" {% if schedule_config.enabled %}checked{% endif %}>
|
|||
|
|
<span>开启定时发送</span>
|
|||
|
|
</label>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="block schedule-grid" id="scheduleControls">
|
|||
|
|
<div>
|
|||
|
|
<label for="schedule_weekday">星期几</label>
|
|||
|
|
<select id="schedule_weekday" name="schedule_weekday" data-schedule-control>
|
|||
|
|
{% for value, label in schedule_weekday_options %}
|
|||
|
|
<option value="{{ value }}" {% if schedule_config.weekday == value %}selected{% endif %}>{{ label }}</option>
|
|||
|
|
{% endfor %}
|
|||
|
|
</select>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<label for="schedule_time">时间</label>
|
|||
|
|
<input type="time" id="schedule_time" name="schedule_time" value="{{ schedule_config.time }}" data-schedule-control>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<input type="hidden" name="schedule_subject" value="{{ schedule_config.subject }}">
|
|||
|
|
|
|||
|
|
<p class="hint">定时任务将发送给“发送对象管理”中的全部邮箱。</p>
|
|||
|
|
|
|||
|
|
<div class="actions">
|
|||
|
|
<button type="submit" class="btn-secondary">保存定时设置</button>
|
|||
|
|
<p class="counter">当前配置: {% if schedule_config.enabled %}已开启{% else %}未开启{% endif %}</p>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
</section>
|
|||
|
|
|
|||
|
|
<section class="panel">
|
|||
|
|
<h2 class="section-title">单次发送</h2>
|
|||
|
|
<form method="post" action="{{ url_for('send_email') }}" id="sendForm">
|
|||
|
|
<div class="grid">
|
|||
|
|
<div class="block">
|
|||
|
|
<label>发送流程</label>
|
|||
|
|
<p class="flow-hint">
|
|||
|
|
点击发送后会自动执行:<strong>全站抓取一次</strong> -> <strong>更新本地向量库</strong> -> <strong>生成并发送最新报告</strong>
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="block">
|
|||
|
|
<label for="subject">邮件主题(可选)</label>
|
|||
|
|
<input
|
|||
|
|
type="text"
|
|||
|
|
id="subject"
|
|||
|
|
name="subject"
|
|||
|
|
placeholder="例如:交通周报(手动发送)"
|
|||
|
|
maxlength="120"
|
|||
|
|
>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="block">
|
|||
|
|
<div class="label-row">
|
|||
|
|
<label>从已管理联系人中选择</label>
|
|||
|
|
<button type="button" class="link-btn" id="toggleManaged">全选 / 全不选</button>
|
|||
|
|
</div>
|
|||
|
|
<div class="recipient-grid" id="managedWrap">
|
|||
|
|
{% if managed_recipients %}
|
|||
|
|
{% for recipient in managed_recipients %}
|
|||
|
|
<label class="recipient-card">
|
|||
|
|
<input type="checkbox" name="managed_recipients" value="{{ recipient }}" class="managed-check">
|
|||
|
|
<span>{{ recipient }}</span>
|
|||
|
|
</label>
|
|||
|
|
{% endfor %}
|
|||
|
|
{% else %}
|
|||
|
|
<p class="hint">暂无已管理收件人,请先在上方新增。</p>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="actions">
|
|||
|
|
<button type="submit" class="btn-primary">单次发送</button>
|
|||
|
|
<p class="counter">已选择联系人 <strong id="selectedCount">0</strong></p>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
</section>
|
|||
|
|
</main>
|
|||
|
|
|
|||
|
|
<script src="{{ url_for('static', filename='js/email_console.js') }}"></script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|