Files
ak 263b98b218 Initial baseline: LaraBlog core with plugin commerce surface.
Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
2026-08-12 01:15:38 +08:00

157 lines
10 KiB
Markdown
Raw Permalink 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.
# LaraBlog 平台一期
## 状态
- 状态:已定稿
- 创建:2026-08-11 17:14
- 最近更新:2026-08-11 17:53
## 背景
SaBlog-X 1.6(约二十年前设计)需迁移到现代 Laravel 栈。迁移目标不是「功能克隆」,而是:**保留有价值的内容、SEO 权重与核心写作/阅读体验**,用当代博客实践替换过时、产垃圾或维护成本不合理的设计。
参考源:https://github.com/neatstudio/sablog-archive
## 现代化取舍原则
1. **内容与 SEO 优先**:文章/分类/标签 ID 与关键旧 URL 保留,避免权重归零
2. **不迁垃圾协议与死技术**Trackback/Pingback、WAP、旧 searchindex、旧 PHP Admin、Feedsky 等一律不实现
3. **用当代能力替换**:AI 评论审核代替巨型敏感词表为主力;对象存储代替本地附件目录;Workerman 承载 LLMFilament 后台
4. **导入可跳过废弃表**`sablog_trackbacks` / `sablog_trackbacklog` / `sablog_searchindex` / `sablog_sessions` 等只记录「已跳过」,不入新库
5. **旧入口若被爬虫打到**:对明确废弃路径返回 **410 Gone**(不实现业务)
## 目标
- 可运行的现代博客:前台阅读/评论/搜索/归档 + Filament 5 后台
- 严格兼容 sablog **内容向**伪静态与关键 query URL;导入后文章/分类 ID 一致
- 多主题、插件框架、SEO/GEO、S3 兼容附件、Workerman AI 运行时
- `sablog:import`:内容与附件上云;跳过过时模块并报告
## 范围
### In scope
1. Laravel 12 + Livewire 4 + Filament 5 + Spatiepermission、settings、feed、sitemap、activitylog
2. 博客核心:文章、分类、标签、评论、附件、友情链接、用户/角色、站点片段(stylevars)
3. Legacy **内容 URL** + 新 canonical(见 URL 矩阵)
4. 主题引擎 + `default` + 示例主题(主题 zip 存本地 `themes/`
5. 插件框架 + payment / membership / plugin-marketplace / theme-marketplace(骨架)+ ai-comment-moderation(可运行管道)
6. SEO/GEOmeta、OG、JSON-LD、sitemap、rss(含 ?cid)、`llms.txt`
7. 对象存储附件全链路 + legacy `/attachment.php``/attachments/{path}`
8. Workerman`ai-content``ai-moderation`
9. `sablog:import` 幂等 upsert + 跳过废弃表报告
10. 防刷:rate limitXSS purifier;附件 MIME 白名单
11. 可选现代增强:文章 `slug`(不取代 `/show-{id}.shtml`
12. **正文格式双轨**`content_format = html|markdown`;站点默认新作为 Markdown;导入默认保留 HTML;可选 HTML→Markdown 转换开关
### Out of scope(明确不迁移 / 不复刻)
- **Trackback / Pingback**(含表、后台、前台、开启开关);`/tburl.php``/trackback.php` 仅 410
- WAP、旧 `searchindex` 搜索缓存表、自建 sessions 表、Feedsky/旧 JS 挂件
-`/admin/*` PHP 后台原样兼容(新后台 Filament `/admin`;旧路径 410
- 旧主题静态 `/templates/default/*` 原样托管
- 真实支付/会员计费/远程商城结算;多站点 SaaS
- Workerman 替代主站 HTTP;绑定单一 LLM 厂商;应用侧长期存附件
- 以巨型政治/广告敏感词表为唯一防垃圾手段(可保留极简词表作预过滤,主力为 AI + rate limit
### 延期(二期+,本期只预留)
**自动配图 / 由正文生成封面**(老 sablog 无现代「特色图」概念):
- 能力意向:
1. **自动配图**:从正文首图 / 附件图 / OG 候选中选封面
2. **生成配图**:用标题+摘要(或 LLM 提示)调用文生图 / 模板渲染,产出封面,写入对象存储
- 执行方式:Workerman / 队列 Job + 可重跑 Artisan 脚本,**批量慢生成**,不堵发布主路径
- 本期只做:表字段与状态枚举预留、`GenerateArticleCoverJob` 空壳、SPEC/清单占位;**不做**真实选图/生图对接
- 封面文件同样只存对象存储,规则同附件
## 方案要点
### 技术栈
| 层 | 选型 |
|---|---|
| 框架 | Laravel 12、PHP 8.2+、Livewire 4 |
| 后台 | Filament 5 |
| Spatie | permission、settings、feed、sitemap、activitylog |
| 附件 | 自建 `attachments` + S3 disk(不用 medialibrary |
| AI | Workerman + Redis`LlmProvider`OpenAI 兼容 + Stub |
| 净化 / 图 | mews/purifierIntervention Image(临时处理后退对象存储) |
### 数据模型
- `articles`id、category_id、user_id、title、content、**content_format(`html`|`markdown`)**、description、keywords、slug(nullable)、published_at、views、comments_count、stick、visible、close_comment、read_password(nullable,兼容旧私密文)、ai_summary、ai_suggestions、legacy_attachments、**cover_***(二期配图预留,见下)
- 封面预留字段:`cover_disk``cover_path``cover_source``none`|`manual`|`attachment`|`content_image`|`generated`)、`cover_status``none`|`pending`|`ready`|`failed`)、`cover_generated_at`
- **无** `trackbacks` 表;**无** `close_trackback` / `trackbacks_count`
### 正文格式(HTML / Markdown
- **原则**:旧 sablog 正文是 HTML**新写作默认 Markdown**(未来主路径)
- **文章级开关**`articles.content_format`;后台编辑器按格式切换(Markdown 文本域 / HTML 富文本)
- **导入双模式**(两份能力,同一命令开关):
1. **`raw`(默认)**:正文保持 HTML`content_format=html`,保留 sablog `[attach=id]`
2. **`markdown`**HTML→Markdown`content_format=markdown`;因 `[]` 是 Markdown 保留字符,**导入时把 `[attach=id]` 改写成 Markdown 安全引用**,不把对象存储 URL 写进库
- **附件引用策略(已定)**
| 场景 | 数据库保存 | 预览/前台输出 |
|---|---|---|
| raw/HTML | `[attach=123]`(原样) | 渲染期解析为 `<img>`/`<a>`href/src 用稳定入口 `/attachment.php?id=123`(再 302 到 S3 |
| markdown | 图片 `![name](attach:123)`;文件 `[name](attach:123)` | CommonMark 后把 `attach:123` 换成 `/attachment.php?id=123` |
- **不在导入时写死 S3/CDN 路径**:避免换桶/换域名后正文失效;**平时 DB 只存引用,输出时转换**
- **站点设置**`default_content_format=markdown`;导入模式由 CLI `--mode=raw|markdown` 决定(可覆盖 settings
- **渲染**`ContentRenderer::toHtml()` = 格式转换 + attach 水合 + Purifier
- `categories``comments`moderation_status`pending`|`pending_ai`|`approved`|`rejected`|`needs_human`)、`tags` + `article_tag``attachments``links``stylevars``plugins``users`password + password_legacy
- Settings:站点、SEO、active_theme、LLM、存储、正文格式默认/导入策略(**无** trackback_enabled
#### 导入映射(摘要)
| 源 | 目标 | 规则 |
|---|---|---|
| articles 核心字段 | articles.* | 保留 id/cid/uid/views/close_comment/read_password 等 |
| articles.content | content + content_format | 默认 `html`;若开启转换则转为 Markdown 且 format=`markdown` |
| articles.trackbacks / closetrackback | — | **忽略** |
| articles.attachments serialize | legacy_attachments + attachments 表 | 文件上云 |
| comments.visible | moderation_status | 1→approved0→pending |
| tags.aids | article_tag | 拆 pivot |
| users.password | password_legacy | 无盐 MD5 → 登录升级 bcrypt |
| attachments.* | attachments.* | 逐条上云,保留 downloads |
| links / stylevars / settings | 对应表/Settings | 直通或键映射 |
| sablog_trackbacks / trackbacklog / searchindex / sessions | — | **跳过并计入报告** |
### 附件与对象存储
- 一律 S3 兼容;临时文件用完即删
- `/attachment.php?id=``/attachments/{path}` → 去重计数后 302
- 正文 `[attach=id]` 解析为对象存储 URL
### URL 矩阵
#### Legacy 内容向(必须业务可达)
`/``/index.php?action=…``/show-{id}[-{page}].shtml``/category-{cid}[-{page}].shtml``/archives…``/tagslist…``/index.php?action=tags&item=``/comments…``/search…``/links.shtml``/reg.shtml``/login.shtml``/rss.xml[?cid=]``/sitemap.xml``/attachment.php``/attachments/{path}``/post.php`(登录/注册/评论/搜索)
#### 新 canonical
- `/tag/{name}`(自旧 tags query 301
- `/llms.txt`
- 可选 `/posts/{slug}`(不取代 show-id
#### 明确废弃(410,无业务)
- `/tburl.php``/trackback.php`
-`/admin/*.php`(非 Filament 面板)
- WAP 相关路径(若出现)
### 主题 / 插件 / Workerman / 导入
同前:主题回退、插件生命周期、AI 双队列、`sablog:import` 幂等与「跳过废弃表」报告;不删源数据。
## 验收标准
- [x] 内容向 Legacy URL 可达;文章/分类 ID 与源一致(`upsertWithId` + fixture 回归)
- [x] **无** Trackback 功能/表/设置;tb 入口 410
- [x] 导入报告含「跳过 trackbacks/searchindex/sessions」计数
- [x] 正文:新建默认 Markdown;导入默认可为 HTML;格式开关可切换;Markdown/HTML 渲染正确;`--mode=markdown`
- [x] 前台评论闭环(含 AI 管道 stub);仅 approved 展示
- [x] Filament 管理内容与配置(含 content_format;无 trackback 菜单)
- [x] 附件对象存储(生产 S3;开发 local);双入口 302;主题可切换;插件可启停
- [x] SEO/GEO 正常;Web 无同步 LLMlegacy MD5 可升级登录
- [x] 导入幂等且不改源
## 开放问题
- [x] 现代化:剔除 Trackback 等过时能力 — 已定
- [ ] 部署环境对象存储凭据;开发可用 MinIO / fake
## 变更记录
| 时间 | 原因 | 变更 |
|------|------|------|
| 2026-08-11 17:14 | 初稿 | 创建 SPEC |
| 2026-08-11 17:20 | qodercli A1A8 | URL/附件/映射等 |
| 2026-08-11 17:25 | qodercli 映射缺口 | 补字段 |
| 2026-08-11 17:26 | 三轮无阻塞;用户确认 | 定稿 |
| 2026-08-11 17:35 | 用户:勿迁 trackback 等过时设计 | 增加现代化取舍;删除 Trackback 全链路;废弃入口 410;导入跳过垃圾表 |
| 2026-08-11 17:42 | 用户:HTML 旧文 / Markdown 未来 | 增加 content_format 双轨、站点/导入开关、可选 HTML→MD 转换 |
| 2026-08-11 17:50 | 用户:导入双份 + attach 与 MD 保留字 | 明确 DB 存引用、渲染期解析;`--mode=raw|markdown`attach: 协议 |
| 2026-08-11 17:53 | 用户:自动配图/生成配图可后推 | 延期章节 + cover 字段/Job 空壳预留 |