feat: 邮件发送历史记录 v1.9.2
This commit is contained in:
@@ -141,6 +141,10 @@ xian-favor/
|
||||
|
||||
## 版本历史
|
||||
|
||||
- v1.9.2 (2026-04-14): 邮件发送历史记录
|
||||
- 详情页面显示邮件发送记录(发送邮箱、时间)
|
||||
- 支持多次发送,显示多条记录
|
||||
- 发送成功/失败状态标记
|
||||
- v1.9.0 (2026-04-14): 发送邮件功能 + 邮箱管理
|
||||
- 每个收藏卡片添加"发送邮件"按钮
|
||||
- 选择已有邮箱或输入新邮箱发送
|
||||
|
||||
BIN
xian_favor/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
xian_favor/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
xian_favor/__pycache__/api.cpython-310.pyc
Normal file
BIN
xian_favor/__pycache__/api.cpython-310.pyc
Normal file
Binary file not shown.
BIN
xian_favor/__pycache__/cli.cpython-310.pyc
Normal file
BIN
xian_favor/__pycache__/cli.cpython-310.pyc
Normal file
Binary file not shown.
BIN
xian_favor/__pycache__/config.cpython-310.pyc
Normal file
BIN
xian_favor/__pycache__/config.cpython-310.pyc
Normal file
Binary file not shown.
BIN
xian_favor/__pycache__/db.cpython-310.pyc
Normal file
BIN
xian_favor/__pycache__/db.cpython-310.pyc
Normal file
Binary file not shown.
@@ -65,6 +65,9 @@ def get_item(item_id):
|
||||
item = db.get_item(item_id)
|
||||
if not item:
|
||||
return jsonify({'success': False, 'error': '条目不存在'}), 404
|
||||
# 获取邮件发送历史
|
||||
email_logs = db.get_email_logs(item_id)
|
||||
item['email_logs'] = email_logs
|
||||
return jsonify({'success': True, 'data': item})
|
||||
|
||||
|
||||
@@ -403,9 +406,14 @@ def send_email():
|
||||
server.sendmail(smtp_user, email_addr, msg.as_string())
|
||||
server.quit()
|
||||
|
||||
# 记录发送日志
|
||||
db.log_email_send(item_id, email_addr, success=True)
|
||||
|
||||
return jsonify({'success': True, 'message': f'已发送到 {email_addr}'})
|
||||
|
||||
except Exception as e:
|
||||
# 记录失败日志
|
||||
db.log_email_send(item_id, email_addr, success=False)
|
||||
return jsonify({'success': False, 'error': f'发送失败: {str(e)}'}), 500
|
||||
|
||||
|
||||
@@ -1143,6 +1151,20 @@ async function showDetail(id) {
|
||||
|
||||
html += `<div class="text-muted small"><strong>创建时间:</strong> ${formatDate(item.created_at)}<br><strong>更新时间:</strong> ${formatDate(item.updated_at)}</div>`;
|
||||
|
||||
// 邮件发送历史
|
||||
if (item.email_logs && item.email_logs.length > 0) {
|
||||
html += `<hr><div class="mb-3"><strong>📧 邮件发送记录:</strong></div>`;
|
||||
html += `<div class="border rounded p-2 bg-light">`;
|
||||
item.email_logs.forEach(log => {
|
||||
const statusIcon = log.success ? '✅' : '❌';
|
||||
html += `<div class="d-flex justify-content-between align-items-center py-1 border-bottom">
|
||||
<span>${statusIcon} 发送到: <strong>${log.email}</strong></span>
|
||||
<span class="text-muted small">${formatDate(log.sent_at)}</span>
|
||||
</div>`;
|
||||
});
|
||||
html += `</div>`;
|
||||
}
|
||||
|
||||
document.getElementById('detailContent').innerHTML = html;
|
||||
|
||||
new bootstrap.Modal(document.getElementById('detailModal')).show();
|
||||
|
||||
@@ -90,6 +90,18 @@ class Database:
|
||||
)
|
||||
""")
|
||||
|
||||
# 邮件发送记录表
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS email_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
item_id INTEGER NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
sent_at TEXT NOT NULL,
|
||||
success INTEGER DEFAULT 1,
|
||||
FOREIGN KEY (item_id) REFERENCES items(id) ON DELETE CASCADE
|
||||
)
|
||||
""")
|
||||
|
||||
# 创建索引
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_items_type ON items(type)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_items_status ON items(status)")
|
||||
@@ -371,6 +383,31 @@ class Database:
|
||||
conn.commit()
|
||||
return cursor.rowcount > 0
|
||||
|
||||
# ============ 邮件日志 操作 ============
|
||||
|
||||
def log_email_send(self, item_id: int, email: str, success: bool = True) -> int:
|
||||
"""记录邮件发送"""
|
||||
now = datetime.now().isoformat()
|
||||
with self.get_conn() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
INSERT INTO email_logs (item_id, email, sent_at, success)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (item_id, email, now, 1 if success else 0))
|
||||
conn.commit()
|
||||
return cursor.lastrowid
|
||||
|
||||
def get_email_logs(self, item_id: int) -> List[Dict[str, Any]]:
|
||||
"""获取收藏的邮件发送记录"""
|
||||
with self.get_conn() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT * FROM email_logs
|
||||
WHERE item_id = ?
|
||||
ORDER BY sent_at DESC
|
||||
""", (item_id,))
|
||||
return [dict(row) for row in cursor.fetchall()]
|
||||
|
||||
def stats(self) -> Dict[str, Any]:
|
||||
"""获取统计信息"""
|
||||
self._ensure_init()
|
||||
|
||||
Reference in New Issue
Block a user