Files
ONE/README.md
T

160 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ONE · 一个博客
一个能跑通全流程的博客 MVP:后台登录 → 写文章(长文 / 短文)→ 发布 → 前台按「07 融合 + Twitter 信息流」风格展示。
- 后端:Go(`net/http` + `database/sql`,SQLite / PostgreSQL 双支持),在 `backend/`
- 前台 + 后台:Vue 3 + Vue Router + Vite,在 `frontend/`(pnpm 管理依赖)
- Markdown:服务端用 `goldmark` 渲染入库,编辑器实时预览用 `marked` + `DOMPurify`
## 一条命令跑起来
```bash
make dev # 后端 8080 + 前端 3000(前端带热更新,已配好 /api 代理)
```
打开 http://localhost:3000 是前台,http://localhost:3000/admin 是后台。
停掉:`make stop`
想要单端口(前端构建产物由 Go 直接托管,接近生产形态):
```bash
make start # 先 pnpm run build,再起 Go,只开 8080
```
打开 http://localhost:8080 。
其它:`make web` 只构建前端、`make server` 只起后端、`make test` 跑后端测试、`make clean` 清构建产物、`make db-reset` 清空本地 SQLite 数据。
## 后台登录
默认账号密码来自环境变量,未设置时是 `admin` / `admin`(启动日志会打印出来):
```bash
ONE_ADMIN_USER=admin ONE_ADMIN_PASSWORD=换一个 make start
```
登录态是服务端签发的 httpOnly cookie(HMAC-SHA256,7 天有效),同时支持 `Authorization: Bearer <token>`,方便用 curl / 脚本写文章。
## 环境变量
| 变量 | 默认 | 说明 |
| --- | --- | --- |
| `ONE_ADDR` | `:8080` | 监听地址 |
| `ONE_DB_DRIVER` | `sqlite` | `sqlite` 或 `postgres` |
| `ONE_DB_DSN` | `./data/one.db` | 数据库连接串(Postgres 示例:`postgres://user:pass@localhost/one?sslmode=disable`) |
| `ONE_ADMIN_USER` | `admin` | 后台用户名 |
| `ONE_ADMIN_PASSWORD` | `admin` | 后台密码 |
| `ONE_SECRET` | 随机生成 | 会话签名密钥;不设的话重启后登录态失效 |
| `ONE_SITE_URL` | `http://localhost:8080` | RSS 里的站点地址,部署时务必改成真实域名 |
| `ONE_WEB_DIST` | `./frontend/dist` | 前端构建产物目录 |
| `ONE_DATA_DIR` | `./data` | SQLite 数据目录 |
## 目录结构
```
backend/ Go 后端(模块名 oneblog)
main.go 路由装配、静态托管 SPA、优雅退出
internal/config 环境变量
internal/db SQLite / PostgreSQL 连接与 `?` → `$n` 占位符重写
internal/model 数据结构
internal/store schema 迁移 + 全部 SQL
internal/render goldmark 渲染、阅读时长估算、摘要截取
internal/api 公开接口 + RSS(/api/*、/rss.xml)
internal/admin 后台接口与登录鉴权(/api/admin/*)
internal/httpx JSON 读写助手
frontend/ Vue 3 前端(pnpm)
src/styles.css 设计 token 与正文排版(07 风格)
src/views 前台:时间线 / 详情 / 归档 / 标签 / 关于
src/admin 后台:登录 / 列表 / 编辑器 / 标签 / 设置
src/components 左栏导航、右栏卡片、时间线行
```
原有那一版 Vue 前端(07 风格重写之前)保留在 git 历史的第一个 commit `edee708` 里,
需要对照或回滚:`git checkout edee708 -- frontend/src`。
## 接口
公开(无需登录):
```
GET /api/site 站点设置
GET /api/posts?kind=&tag=&q=&page=&size= 已发布文章(kind: long|short)
GET /api/posts/:slug 文章详情
GET /api/archive 按年 → 月分组
GET /api/tags 标签与计数
GET /rss.xml (/feed 同) RSS 2.0
```
后台(需登录):
```
POST /api/admin/login {username,password} → {token}
POST /api/admin/logout
GET /api/admin/me
GET /api/admin/posts?status=&kind=&q=&page=&size=
POST /api/admin/posts 新建
GET /api/admin/posts/:id
PUT /api/admin/posts/:id 更新(编辑器自动保存走这里)
DELETE /api/admin/posts/:id
GET /api/admin/tags
POST /api/admin/tags {name}
PUT /api/admin/tags/:id {name}
DELETE /api/admin/tags/:id
GET /api/admin/settings
PUT /api/admin/settings
```
`Post` 的关键字段:`kind`(`long` / `short`)、`title`、`slug`、`summary`、`content_md`、`content_html`、`status`、`published_at`、`reading_minutes`、`tags[]`。
短文没有可见标题,但 `title` 仍会由正文首句生成,供归档与标签列表索引。
## 部署
生产形态是「一个二进制 + 一个静态目录」:
```bash
make build # 产出 ./one-server,前端已打进 web/dist
ONE_ADDR=:8080 \
ONE_SITE_URL=https://your.domain \
ONE_DB_DRIVER=postgres \
ONE_DB_DSN="postgres://user:pass@127.0.0.1/one?sslmode=disable" \
ONE_SECRET=一串随机长字符串 \
ONE_ADMIN_PASSWORD=强密码 \
./one-server
```
要点:
- **静态资源**:Go 直接托管 `web/dist`,未知路径回落到 `index.html`,所以 `/post/xxx`、`/admin` 刷新都不会 404。
- **反向代理**:前面挂 Nginx / Caddy 时把 `/` 反代到 `ONE_ADDR` 即可;如果只在内网监听,可以不挂。
- **SQLite 部署**:把 `data/` 挂到持久卷;并发写很低的博客足够用(已开 WAL + busy_timeout)。
- **PostgreSQL 部署**:改 `ONE_DB_DRIVER` 与 `ONE_DB_DSN`,schema 会在启动时自动创建,无需手动迁移。
- **systemd 示例**:
```ini
[Unit]
Description=ONE blog
After=network.target
[Service]
WorkingDirectory=/opt/one
Environment=ONE_ADDR=:8080 ONE_SITE_URL=https://your.domain ONE_SECRET=xxx ONE_ADMIN_PASSWORD=xxx
ExecStart=/opt/one/one-server
Restart=always
[Install]
WantedBy=multi-user.target
```
- **备份**:SQLite 直接拷 `data/one.db`(停写更稳);Postgres 用 `pg_dump`。
## 已验证
`make start` 后:后台登录 → 写长文与短文 → 发布 → 前台时间线(长文标题 + 摘要 / 短文正文铺开)、详情、归档、标签、RSS 全部可见;
编辑器改正文 1.5 秒后自动保存到服务端;桌面与移动宽度无横向滚动;SQLite 路径全流程跑通,PostgreSQL 的占位符重写有单元测试覆盖(本机没有 Postgres 实例,未做端到端验证)。
## 待确认
- 仓库地址:本仓库是在本地 `/Users/cjun/Code/one` 新建的 git 仓库,还没有 remote。给个地址就能推上去并绑进工作区。
- 鉴权方式:目前是账号密码 + 签名 cookie。想改成纯 token 也可以,接口已经兼容 `Authorization: Bearer`。
- 图片上传:MVP 未做,正文里先用图片外链。