拾光备忘录
拾光备忘录 · 项目知识库
拾光备忘录 = 网址收藏 + 备忘录 + 定时提醒(网页版 + Windows 桌面版双端) 名称由来:藏(藏住常用网址)+记(记下大小事、到点不忘)

一、项目概述
| 项 | 内容 |
|---|---|
| 定位 | 个人效率小工具:网址收藏 / 备忘录 / 定时提醒 三合一 |
| 形态 | 网页版(多用户在线)+ Windows 桌面版(本地离线可用) |
| 数据 | 网页版 MySQL;桌面版本地 SQLite(登录后可同步到服务器) |
| 开发栈 | 网页:PHP 单文件 + MySQL;桌面:Python + pywebview(WebView2) + pythonnet + pystray |
| 部署形态 | 单文件 PHP 应用(index.php 自动建表),任意 PHP 主机可跑 |
| 图标 | 红底白字「陈」(favicon,全项目统一) |
| 正式服务器 | https://bwl.kqwq.com/ |
二、功能清单
网页版

- 网址收藏:批量添加 / 单条编辑 / 复制网址 / 软删除(回收站) / 置顶 / 访问计数 / 搜索
- 备忘录:富文本编辑(wangEditor)/ 历史版本恢复(note_history)/ 导出备份
- 定时提醒:时间 + 内容 + 方式(电脑窗口 / 邮件 / Bark / 企业微信),到点推送
- 多用户系统:注册 / 登录 / 忘记密码(邮箱验证码)/ 改密码
- 管理后台(admin):仪表盘 / 用户管理(角色/停用/删除)/ 登录日志 / 公告设置 / 站点设置(TDK、SMTP、开关)
- PWA:manifest + sw.js,手机添加到主屏幕当 App 用
- 界面设置:用户自己开关「网址/备忘/提醒」三个面板
- 介绍页(未登录默认页):功能卡片 + 三步用法 + 在线/离线对比 + CTA
桌面版

- 系统托盘:最小化到托盘、托盘菜单(打开主界面/退出)
- 准点提醒:按 remind_at 精确 setTimeout + Python watchdog 双路兜底,到点弹 WinForms 提醒窗
- 提醒方式:电脑弹窗(手动关闭)/ 邮件 / Bark / 企业微信(与网页端同步)
- 顶部菜单:工具(精简模式/导出备份/深色模式/退出)、设置、关于(帮助/作者)、账号(登录/立即同步/退出)
- 离线优先:不登录本地可用,登录后与服务器双向同步(本地缓存 + 待同步队列)
- 精简模式:小窗口专注备忘录;深色模式;窗口位置/尺寸记忆
下载中心
藏记 · 桌面助手 —— 网址、备忘录、提醒,一台电脑全搞定

三、技术架构
┌─ 网页版(服务器)────────────────────────────┐
│ index.php ← 单文件:页面 + API + 自动建表 │
│ cron.php ← CLI:每分钟扫描到期提醒并推送 │
│ download.php ← 桌面版下载页 │
│ config.php ← MySQL 连接配置 │
│ vendor/ ← PHPMailer / wangEditor │
│ MySQL:users urls notes reminders settings │
│ user_settings note_history login_logs │
│ audit_logs │
└──────────────────────────────────────────────┘
▲ 同步(HTTP API)
┌─ 桌面版(Windows)───────────────────────────┐
│ app.py ← pywebview 窗口 + 托盘 + WinForms 弹窗│
│ server.py ← 本地 HTTP 服务(127.0.0.1:876x) │
│ core.py ← 配置默认值 / 提醒方式定义 │
│ index.html ← 前端(与网页版同源,桌面内置一份) │
│ SQLite ← 本地缓存 + 待同步队列 │
└──────────────────────────────────────────────┘
关键机制
- 双路提醒防漏:前端准点 setTimeout(窗口可见时)+ Python watchdog 每 10 秒扫本地缓存(最小化被节流时兜底)
- 双路防重:前端 notify 带提醒 id → server 记入
STATE._fired→ watchdog 见同 id 跳过 - 最小化状态同步:app.py 最小化/恢复时
_push_hidden后台线程 evaluate_js 通知前端winHidden - 提醒状态同步:前端 fireDue 与 watchdog 触发后都会调
reminders/done,列表自动标"已提醒" - 桌面端数据流:启动自动登录(config 凭据)→ 拉服务器数据 → 本地 SQLite 缓存 → 修改写缓存 + 待同步队列 → 手动/定时同步
四、数据模型(MySQL)
| 表 | 关键字段 | 说明 |
|---|---|---|
| users | id, username, password(bcrypt), email, role(admin/user), status | 用户;首用户需 SQL 提权为 admin |
| urls | id, user_id, url, title, note, fav, pinned, clicks, deleted_at | 网址;deleted_at 非空=回收站 |
| notes | id, user_id, content, updated_at | 备忘录 |
| note_history | id, note_id, content, created_at | 历史版本(恢复用) |
| reminders | id, user_id, remind_at, content, method, target, done | 提醒;done=已发送 |
| settings | k, v | 站点设置:site_title/TDK、SMTP、公告、开关 |
| user_settings | user_id, k, v | 用户界面偏好(面板开关) |
| login_logs | user_id, username, ip, ua, login_time | 登录日志 |
| audit_logs | username, action, detail, ip, created_at | 后台操作审计 |
表由 index.php 首次访问自动 CREATE TABLE IF NOT EXISTS 创建,无需手动导 SQL。
五、使用手册
网页版
- 打开站点 → 介绍页 → 「注册使用」注册账号(邮箱选填,忘记密码需邮箱)
- 登录后三面板:
- 网址:搜索框模糊搜,+添加网址(一行一个),点📌置顶、✎编辑、🗑删除(进回收站可恢复)
- 备忘录:富文本编辑,自动保存,「历史」可恢复旧版本,「导出」备份
- 提醒:时间 + 内容 + 方式;列表点时间或状态弹窗看完整内容
- 管理后台(admin):右上角「⚙ 后台」→ 用户管理 / 公告 / 站点设置(SMTP、网站标题等)
桌面版
- 双击 exe 即用;同目录 config.json 的
api_base决定连哪台服务器 - 顶部菜单:工具(精简/导出/深色/退出)、设置、关于、账号
- 账号菜单:未登录「登录…」;登录后「立即同步 / 退出登录」
- 提醒弹窗:屏幕居中圆角弹窗(标题固定「⏰ 定时提醒」,点「知道了」确认),最小化到托盘也弹
- 精简模式:工具→精简模式,窗口缩到 460 宽专注备忘录,再点恢复完整
六、部署指南(简版)
云服务器(宝塔)
- 宝塔装 Nginx + PHP 8.0~8.2(pdo_mysql)+ MySQL 5.7/8.0
- 添加数据库,记库名/账号/密码
- 上传 server/ 目录到网站根目录
- 改 config.php 的 5 项数据库连接
- 访问域名 → 自动建表
- 注册账号 → phpMyAdmin 执行:
UPDATE users SET role='admin' WHERE username='你的账号'; - 宝塔计划任务:每分钟执行
php /www/wwwroot/域名/cron.php(定时提醒必需) - 后台配 SMTP(QQ 邮箱授权码)→ 忘记密码验证码可用
- 宝塔一键 SSL
内网自用
一台常开电脑装 phpstudy → 同上 → 站点绑 192.168.x.x → 局域网访问。
桌面版分发
备忘录助手.exe + config.json 打包 zip;config.json 的 api_base 改成你的服务器地址;用户双击即用,不登录可本地用。
更新方式
网页版:替换 index.php 一个文件(先备份数据库);桌面版:替换 exe。
七、开发记录 · 踩过的坑(重要)
| 现象 | 根因 | 解决方案 |
|---|---|---|
| 最小化后无法还原、进程无响应 | tray 线程直接跨线程调 WinForms form.Show() → UI 线程死锁 |
ctypes ShowWindow 恢复窗口;WinForms 操作 form.BeginInvoke 投递回 UI 线程 |
| 精简模式切回后窗口拖不动 | WinForms MaximumSize 设过后不自动清除,传 None 被跳过残留 (460,屏高) |
_set_limits None 分支显式设 MaximumSize = Size(0,0)(0,0=无限制) |
| 提醒弹两次 | 前端 fireDue 与 Python watchdog 双路各自防重没打通 | 前端 notify 带 id → server 记 STATE._fired → watchdog 同 id 跳过 |
| notify_cb 初始化两次 | pywebview loaded 事件偶发触发两次 | _setup_tray 加 _TRAY_SETUP_DONE 防重标志 |
| 桌面版"未连接服务器"但状态显示已连接 | config.json 密码被清空(设置弹窗密码留空保存→覆盖)+ 服务端 admin 密码被改 | save_settings 空密码不覆盖;config 补回正确密码 |
| 提醒后状态不更新 | 托盘弹窗无"点知道了"回调通道,服务端 done 没标 | fireDue/watchdog 触发后都调 reminders/done;前端轮询跳过 done |
| 修改现有定时后不生效 | firedIds/_fired 里有旧记录 → 新定时器不重建 | saveRem 后 unfireRem(id);server save 后 STATE._fired.discard(id) |
| 弹窗纯白背景看不清 | 白底在浅色屏幕无边界 | 弹窗底色改浅紫 #f5f3ff,内容区留白卡片 |
| 介绍页整体错乱 | 登录页 CSS body{flex 居中} + .box{width:340px} 挤压宽页;body 内 <style> 不生效 |
body:has(.landing) 条件覆盖 + .box{display:contents} |
| 提醒"删除"两字换行 | 侧栏 flex 挤压按钮 | .r-del{white-space:nowrap} |
| 侧栏提醒内容不显示 | r-content 被省略号截没 | 列表不显示内容,点时间/状态弹窗看完整 |
八、版本历史
| 版本 | 内容 |
|---|---|
| W28 | 准点提醒(setTimeout + watchdog 兜底)、托盘 WinForms 弹窗 |
| W29 | 弹窗改手动关闭(不自动消失)、屏幕居中 |
| W30 | 修复双弹、最小化还原崩溃(跨线程)、notify_cb 双注入 |
| W31 | 弹窗标题固定「⏰ 定时提醒」、提醒状态自动 done、编辑定时生效 |
| W32 | 命名「小陈备忘录」、顶部菜单(账号/深色)、config 密码修复、精简模式拖拽修复 |
| W33 | 菜单排序(工具/设置/关于/账号)、删除整个 header |
| W34 | 弹窗背景色(浅紫+白卡片) |
| 网页端 | 介绍页、登录独立页、命名「藏记」、导航 sticky、公告窄条居中、提醒点击查看 |
九、常见问题 FAQ
Q:桌面版同步提示"未连接服务器"但左下角显示已连接?
A:多为 config.json 账号密码失效(服务端改过密码或密码被设置弹窗清空)。账号菜单重新登录,或检查 config.json 的 username/login_password。
Q:自部署后定时提醒不触发?
A:检查宝塔计划任务是否配置 cron.php 每分钟执行;再检查提醒方式配置(Bark 需 Key、邮件需 SMTP)。
Q:第一个注册的用户进不了后台?
A:需手动 SQL 提权:UPDATE users SET role='admin' WHERE username='账号';
Q:网页版忘记密码收不到验证码?
A:后台站点设置需配置 SMTP(QQ 邮箱授权码);注册时必须填过邮箱。
Q:桌面版数据在哪?
A:本地 SQLite 在 exe 同目录 data/ 下;「工具 → 导出数据备份」可导出。
Q:怎么升级?
A:网页版替换 index.php(先 mysqldump 备份);桌面版替换 exe,config.json 保留。