现代化网址收藏与备忘录应用,基于 Cloudflare Pages + Workers + D1 构建的全栈应用。
📌 在线演示: https://so.it0731.cn
📌 原项目: 重构自 so.sztcrs.com
- 多搜索引擎切换(百度、Google、必应、搜狗、360)
- 只展示管理员维护的公开导航
- 分类导航标签
- 常用推荐(按访问次数排序)
- 响应式设计
- 只管理当前用户自己的私有收藏
- 添加 / 编辑 / 删除收藏
- 收藏 / 归档
- 私有分类管理
- 标签系统
- 搜索和筛选
- 导出 JSON
- 导出浏览器书签 HTML
- 导入浏览器书签 HTML
- 从私有收藏发起“申请分享到公开导航”
- 用户提交链接申请公开分享
- 管理员审核通过 / 拒绝
- 审核通过后自动进入公开导航
- 原私有收藏保留不变
- Tiptap 富文本编辑器
- 修复输入时光标丢失问题
- 置顶功能
- 颜色标记
- 分类和标签支持
- 网页信息抓取(标题 / 描述 / 图标)
- 图标加载失败自动显示标题首字符
- 管理员公开分类管理页
- 管理员审核页
| 层级 | 技术 | 说明 |
|---|---|---|
| 前端 | React 18 + TypeScript + Vite | SPA 构建 |
| UI | TailwindCSS + Lucide React | 响应式组件 |
| 后端 | Cloudflare Workers | Serverless API |
| 数据库 | Cloudflare D1 (SQLite) | 持久化 |
| 部署 | GitHub Actions + Cloudflare | 自动部署 |
SimpliSave/
├── src/
│ ├── pages/
│ │ ├── Home.tsx # 公开导航首页
│ │ ├── Bookmarks.tsx # 私人收藏夹
│ │ ├── Memos.tsx # 备忘录
│ │ └── admin/
│ │ ├── AdminCategories.tsx # 公开分类管理
│ │ └── AdminSubmissions.tsx # 分享审核
│ ├── components/
│ │ └── Favicon.tsx # 图标降级组件
│ ├── services/api.ts # 前端 API 层
│ └── stores/
├── workers/
│ ├── api/
│ │ ├── publicBookmarks.ts # 公开导航 API
│ │ ├── userBookmarks.ts # 私人收藏 API
│ │ ├── submissions.ts # 审核流 API
│ │ ├── categories.ts # 公开/私有分类 API
│ │ ├── importExport.ts # HTML 导入导出 API
│ │ └── fetchMeta.ts # 网页信息抓取 API
│ └── index.ts
├── schema.sql # v3 数据库结构
└── package.json
public_card_groups(卡片组)public_bookmarks(子链接)public_categories
user_bookmarksuser_categories
bookmark_submissions
usersmemostags
点击右上角 Fork。
- 访问 https://dash.cloudflare.com/profile/api-tokens
- 点击 Create Token
- 选择 Edit Cloudflare Workers 模板
- 权限至少包括:
- Account → Cloudflare Pages → Edit
- Account → Workers → Edit
- Account → D1 → Edit
- 创建 Token 并复制
登录 Cloudflare Dashboard,在右侧边栏复制 Account ID。
- Workers & Pages → D1
- 创建数据库
simplisave-db - 进入数据库设置,复制 Database ID
仓库地址:
https://github.com/你的用户名/SimpliSave/settings/secrets/actions
添加:
| Name | 说明 |
|---|---|
CF_API_TOKEN |
Cloudflare API Token |
CF_ACCOUNT_ID |
Cloudflare Account ID |
D1_DATABASE_ID |
D1 Database ID |
JWT_SECRET |
JWT 签名密钥 |
WORKERS_URL |
首次部署 Workers 后填写实际地址 |
JWT_SECRET可使用:openssl rand -hex 32
推送代码后,GitHub Actions 会先尝试部署 Workers。
git push部署成功后,在 Cloudflare Dashboard 中打开 simplisave-api,复制 Workers URL,类似:
https://simplisave-api.xxx.workers.dev
将它填写到 GitHub Secret:WORKERS_URL
然后2选1: 方法1.在GITHUB Actions里面找到deploy-pages脚本重行运行一次 方法2.再次推送触发 Pages 使用正确后端地址重新构建:
git commit --allow-empty -m "chore: trigger redeploy"
git push执行:
schema.sql:创建 v3 表结构
建议在 Cloudflare D1 的 Query 中执行。
- 将sql粘贴到Query中,点Run按钮右边下拉三角,选择 Run all statement
打开 simplisave-api Worker:
-
D1 database bindings
- Variable name:
DB - Database:
simplisave-db
- Variable name:
-
Environment variables / Secrets
JWT_SECRETENVIRONMENT=production
- 在workers 和 pages页面找到你的pages域名类似于 :
https://simplisave.pages.dev/
https://<your-workers-url>/public-bookmarks
| 文件 | 用途 |
|---|---|
schema.sql |
v3 完整建表结构 |
POST /auth/registerPOST /auth/loginGET /auth/mePUT /auth/profile
GET /card-groups— 列出卡片组GET /card-groups/by-slug/:slug— 卡片组详情(含子链接)POST /card-groups(管理员)PUT /card-groups/:id(管理员)DELETE /card-groups/:id(管理员)POST /card-groups/:id/visit— 记录访问
GET /public-bookmarks?group_id=...POST /public-bookmarks(管理员)PUT /public-bookmarks/:id(管理员)DELETE /public-bookmarks/:id(管理员)
GET /user-bookmarksPOST /user-bookmarksPUT /user-bookmarks/:idDELETE /user-bookmarks/:idGET /user-bookmarks/exportGET /user-bookmarks/export-htmlPOST /user-bookmarks/import
GET /public-categoriesPOST /public-categories(管理员)GET /user-categoriesPOST /user-categories
POST /submissionsGET /submissions(管理员)PUT /submissions/:id/approve(管理员)PUT /submissions/:id/reject(管理员)
GET /memosPOST /memosPUT /memos/:idDELETE /memos/:idPOST /memos/:id/pin
GET /fetch-meta?url=...
确认:
WORKERS_URL已正确填写到 GitHub Secrets- Worker 已绑定 D1
- Pages 已重新构建
确认导入文件是浏览器导出的标准书签 HTML。
已内置降级逻辑,会自动显示标题首字符。
确认数据库里该用户 role='admin'。
现象:访问 simplisave-9a6.pages.dev(主域名)会提示 Nothing is here yet,但访问 master.simplisave-9a6.pages.dev 却能正常看到网页。 解决方法:
- 在 Pages 项目页面,点击 Settings -> Builds & deployments。
- 找到 Production branch(生产分支)设置,查看它当前指向的是不是 master。 如果不是,将其修改为 master。
- 修改后必须重新触发一次部署(去 master 分支随便提交一个空 commits,或者在 - Deployments 页面点击重新部署),让它生成一个带有 Production 标签的最新版本。
MIT License
Made with ❤️ by 52op