Compare commits

...

26 Commits

Author SHA1 Message Date
6b775c99f9 feat: 已完成待办可重新打开
- 新增 /api/items/<id>/reopen 接口
- 前端列表已完成待办显示重新打开按钮
- 恢复为 pending 或 in_progress 状态
2026-04-16 11:05:34 +08:00
061bfa3b55 docs: 更新版本历史 v1.10.0 2026-04-16 10:59:44 +08:00
2eccc11369 feat: 网页端待办到期提醒功能
- 新增 /api/reminders API 接口
- 获取已过期、今天到期、即将到期的待办
- 前端显示提醒栏和弹窗详情
- 每5分钟自动刷新提醒
- 支持快速完成待办
2026-04-16 10:59:26 +08:00
d874577458 feat: 邮件发送历史记录 v1.9.2 2026-04-14 17:27:37 +08:00
bc59fb39db fix: 邮件发送添加Date和Reply-To头 2026-04-14 17:09:04 +08:00
fba2c1290d fix: 端口587无SSL直接连接 2026-04-14 16:40:57 +08:00
6490ceff08 fix: SMTP配置更新为mail.tphai.com端口587 2026-04-14 16:35:20 +08:00
e13fa0e337 feat: 发送邮件功能 + 邮箱管理 v1.9.0 2026-04-14 12:52:49 +08:00
3eae1595aa fix: 修复AI处理f-string中JSON花括号转义问题 2026-04-13 17:03:09 +08:00
6f0905d83a docs: 更新版本历史 2026-04-13 16:57:02 +08:00
033b7509d7 feat: AI自动添加功能,智能识别文本类型并整理数据 2026-04-13 16:56:43 +08:00
8f9a8d2ad5 docs: 更新版本历史 2026-04-13 16:46:10 +08:00
ffe7adcad2 feat: 编辑收藏时支持更改类型,动态显示对应字段 2026-04-13 16:45:48 +08:00
963dd1846b docs: 更新版本历史 2026-04-13 16:35:35 +08:00
ad6d369069 feat: 标签管理添加编辑功能,支持修改标签名称 2026-04-13 16:35:09 +08:00
68411813b3 docs: 更新版本历史 2026-04-13 16:27:56 +08:00
d8780b9000 fix: 标签管理添加搜索功能,实时过滤标签列表 2026-04-13 16:27:36 +08:00
196bfaf213 docs: 更新版本历史 2026-04-13 16:17:23 +08:00
2675edb695 feat: 首页添加分页功能,每页20条记录 2026-04-13 16:17:06 +08:00
1f9d0a7ea2 docs: 更新版本历史 2026-04-13 16:10:41 +08:00
4642a278a5 feat: 首页添加导出按钮,一键导出JSON格式 2026-04-13 16:10:27 +08:00
598a86b32d docs: 更新版本历史 2026-04-13 16:01:20 +08:00
ae27641b6d feat: 编辑和添加模态框改为大尺寸(modal-lg) 2026-04-13 16:01:06 +08:00
7ab6647c32 docs: 更新版本历史 2026-04-13 12:27:08 +08:00
4d51a680aa fix: 备注改名为详情,支持换行显示,扩大输入框 2026-04-13 12:21:37 +08:00
e2db77e93f docs: 更新版本历史 2026-04-13 12:14:25 +08:00
8 changed files with 1319 additions and 42 deletions

View File

@@ -96,6 +96,11 @@ API端点
| `/api/tags` | GET | 列出标签 |
| `/api/tags` | POST | 创建标签 |
| `/api/tags/<id>` | DELETE | 删除标签 |
| `/api/emails` | GET | 列出邮箱 |
| `/api/emails` | POST | 创建邮箱 |
| `/api/emails/<id>` | PUT | 更新邮箱 |
| `/api/emails/<id>` | DELETE | 删除邮箱 |
| `/api/send-email` | POST | 发送收藏到邮箱 |
| `/api/stats` | GET | 统计信息 |
| `/api/search` | GET | 搜索 (参数 q=关键词) |
@@ -136,6 +141,39 @@ xian-favor/
## 版本历史
- v1.10.0 (2026-04-16): 网页端待办到期提醒功能
- 新增提醒 API `/api/reminders`
- 获取已过期、今天到期、即将到期的待办
- 前端顶部提醒栏显示提醒数量和概要
- 弹窗详情支持快速完成待办
- 每5分钟自动刷新提醒
- v1.9.2 (2026-04-14): 邮件发送历史记录
- 详情页面显示邮件发送记录(发送邮箱、时间)
- 支持多次发送,显示多条记录
- 发送成功/失败状态标记
- v1.9.0 (2026-04-14): 发送邮件功能 + 邮箱管理
- 每个收藏卡片添加"发送邮件"按钮
- 选择已有邮箱或输入新邮箱发送
- 新邮箱自动保存到邮箱管理
- 邮箱管理页面:添加、编辑、删除邮箱
- SMTP配置支持环境变量SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS
- v1.8.0 (2026-04-13): AI自动添加功能智能识别文本类型并整理数据
- 首页新增"AI添加"按钮
- 粘贴文本/链接/笔记等AI自动识别类型并提取关键信息
- 支持文本、链接、专栏、待办四种类型自动识别
- 自动生成标签和标题
- v1.7.0 (2026-04-13): 编辑收藏时支持更改类型,动态显示对应字段
- v1.6.0 (2026-04-13): 标签管理添加编辑功能,支持修改标签名称
- v1.5.1 (2026-04-13): 标签管理添加搜索功能,实时过滤标签列表
- v1.5.0 (2026-04-13): 首页添加分页功能每页20条记录
- v1.4.0 (2026-04-13): 首页添加导出按钮一键导出所有收藏为JSON文件
- v1.3.2 (2026-04-13): 编辑和添加模态框改为大尺寸(modal-lg)
- v1.3.1 (2026-04-13): 备注改名为详情,支持换行显示,扩大输入框
- v1.3.0 (2026-04-13): 标签管理功能和输入自动提示
- 侧边栏新增"标签管理"入口
- 标签管理页面:显示所有标签、使用条目数、创建/删除标签
- 添加/编辑时标签输入支持自动提示(输入时显示匹配的已有标签)
- 点击提示标签快速添加
- v1.2.1 (2026-04-13): 卡片显示两行,第二行显示内容预览
- v1.2.0 (2026-04-13): 压缩首页卡片高度,更紧凑的列表布局
- v1.1.1 (2026-04-13): 编辑备注改为多行输入框

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -80,6 +80,28 @@ class Database:
)
""")
# 邮箱表
cursor.execute("""
CREATE TABLE IF NOT EXISTS emails (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
name TEXT,
created_at TEXT NOT NULL
)
""")
# 邮件发送记录表
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)")
@@ -244,6 +266,18 @@ class Database:
""")
return [dict(row) for row in cursor.fetchall()]
def update_tag(self, tag_id: int, name: str) -> bool:
"""更新标签名称"""
with self.get_conn() as conn:
cursor = conn.cursor()
# 检查名称是否已存在(排除自己)
cursor.execute("SELECT id FROM tags WHERE name = ? AND id != ?", (name, tag_id))
if cursor.fetchone():
return False # 名称已存在
cursor.execute("UPDATE tags SET name = ? WHERE id = ?", (name, tag_id))
conn.commit()
return cursor.rowcount > 0
def delete_tag(self, tag_id: int = None, name: str = None) -> bool:
"""删除标签"""
with self.get_conn() as conn:
@@ -290,6 +324,90 @@ class Database:
""", (item_id,))
return [row['name'] for row in cursor.fetchall()]
# ============ Email 操作 ============
def create_email(self, email: str, name: str = None) -> int:
"""创建邮箱"""
now = datetime.now().isoformat()
with self.get_conn() as conn:
cursor = conn.cursor()
try:
cursor.execute("INSERT INTO emails (email, name, created_at) VALUES (?, ?, ?)",
(email, name, now))
conn.commit()
return cursor.lastrowid
except sqlite3.IntegrityError:
# 邮箱已存在返回已有ID
cursor.execute("SELECT id FROM emails WHERE email = ?", (email,))
return cursor.fetchone()['id']
def list_emails(self) -> List[Dict[str, Any]]:
"""列出所有邮箱"""
with self.get_conn() as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM emails ORDER BY created_at DESC")
return [dict(row) for row in cursor.fetchall()]
def get_email(self, email_id: int) -> Optional[Dict[str, Any]]:
"""获取单个邮箱"""
with self.get_conn() as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM emails WHERE id = ?", (email_id,))
row = cursor.fetchone()
return dict(row) if row else None
def update_email(self, email_id: int, email: str = None, name: str = None) -> bool:
"""更新邮箱"""
now = datetime.now().isoformat()
with self.get_conn() as conn:
cursor = conn.cursor()
if email:
# 检查邮箱是否已存在(排除自己)
cursor.execute("SELECT id FROM emails WHERE email = ? AND id != ?", (email, email_id))
if cursor.fetchone():
return False # 邎箱已存在
if email and name:
cursor.execute("UPDATE emails SET email = ?, name = ? WHERE id = ?", (email, name, email_id))
elif email:
cursor.execute("UPDATE emails SET email = ? WHERE id = ?", (email, email_id))
elif name:
cursor.execute("UPDATE emails SET name = ? WHERE id = ?", (name, email_id))
conn.commit()
return cursor.rowcount > 0
def delete_email(self, email_id: int) -> bool:
"""删除邮箱"""
with self.get_conn() as conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM emails WHERE id = ?", (email_id,))
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()
@@ -315,6 +433,59 @@ class Database:
stats['tags'] = cursor.fetchone()['count']
return stats
# ============ 提醒相关 ============
def get_reminders(self) -> Dict[str, Any]:
"""获取提醒信息:即将到期和已过期的待办"""
self._ensure_init()
with self.get_conn() as conn:
cursor = conn.cursor()
now = datetime.now()
reminders = {
'overdue': [], # 已过期
'due_today': [], # 今天到期
'due_soon': [] # 24小时内到期不含今天
}
# 查询未完成的待办(有截止日期的)
cursor.execute("""
SELECT * FROM items
WHERE type = 'todo'
AND status != 'completed'
AND due_date IS NOT NULL
AND due_date != ''
ORDER BY due_date ASC
""")
for row in cursor.fetchall():
item = dict(row)
item['tags'] = self._get_item_tags(conn, item['id'])
try:
due_date = datetime.strptime(item['due_date'], '%Y-%m-%d')
# 计算距离到期的时间
days_left = (due_date.date() - now.date()).days
if days_left < 0:
# 已过期
item['days_overdue'] = abs(days_left)
reminders['overdue'].append(item)
elif days_left == 0:
# 今天到期
reminders['due_today'].append(item)
elif days_left == 1:
# 明天到期24小时内
reminders['due_soon'].append(item)
except ValueError:
# 日期格式错误,跳过
continue
# 统计总数
reminders['total'] = len(reminders['overdue']) + len(reminders['due_today']) + len(reminders['due_soon'])
return reminders
# 全局数据库实例