# RainWeb v2 全面升级计划 > v1(原生 HTML/CSS/JS + PJAX)→ v2(React 前后台分离 + 后端改造)。用户确认的选型全部定案,本计划为唯一执行依据。 > 旧 `docs/refactor-plan.md` 的后端部分(P0/P1/P2 中安全与数据库项)并入本计划;其前端路由项(P1-14 方案 A、P2-19 方案 B)**作废**——由 React Router 取代。 > 本计划未开始任何代码改动,待用户确认后按阶段执行。 ## 0. 选型定案(已确认,不再变更) | 项 | 决定 | |---|---| | 前端框架 | **React + Vite**(TS 可选,见 §4.1) | | 前台 UI | **不引 UI 库**,手写组件 + 复用 `public/css/style.css`,**UI 100% 还原** | | 后台 | **独立应用**(独立入口 `/admin`),引入 **MUI** | | 工程组织 | **单 Vite 项目多入口**(前台 + 后台两个 HTML 入口) | | SEO | **保留 ssr.js 双轨**(/blog/:id、/forum/:id、sitemap.xml 不变) | | 数据库 | **better-sqlite3 + Node 22 LTS**(替换 sql.js) | | 后端改造 | 原 P0 止损 + P1 安全加固照旧执行 | ## 1. 目标架构 ``` 浏览器 ├── 前台 SPA(/) React + React Router,构建产物 + style.css,占位符机制保留 │ └── 导航「管理后台」按钮 → 整页跳转 /admin(浏览器级导航,非 SPA 路由、非 iframe) ├── 后台 SPA(/admin) React + MUI,完全独立入口/独立路由/独立登录态,外部面板嵌入保留 └── SEO 直链(/blog/:id 等) ssr.js 服务端渲染(不变) ↓ Express 4(server.js) ├── /api/* 15 个路由模块(契约不变,前端重写以现有 API 为基) ├── 静态:构建产物 + uploads/ + public/wallpaper/ └── SPA fallback:/ → 前台 index.html;/admin* → 后台 index.html ↓ better-sqlite3(data/rainweb.db,零迁移直接打开) ``` **前后台关系**:两个独立 React 入口(单 Vite 多入口构建),互相之间仅通过整页跳转连接。前台无后台路由、后台无前台路由;登录态共用(同一 JWT,localStorage)。 ## 2. v1 → v2 保留 / 废弃清单 **保留**:后端全部(routes/、middleware/、db.js 逻辑、ssr.js、cli.js 改造后)、`public/css/style.css`(搬入前台)、`public/wallpaper/`、`uploads/`、API 契约。 **废弃**:`public/index.html` 等全部页面 HTML(改 React 组件)、`public/js/` 全部(api/nav/router/theme/captcha/render/music-embed/main/blog/forum/admin/passwords → 拆成 React 模块)、PJAX 机制(router.js)、`public/js/main.js` 等死代码。 **保留功能点(迁移时必须覆盖)**:博客瀑布流、论坛多分类/子分类/发帖回复、密码管理器(PIN + AES-256-GCM,见 §4.4)、管理面板聚合(iframe 嵌入 + proxy 代理)、壁纸/磨砂玻璃/深浅色主题、音乐嵌入(自动隐藏)、验证码(内置/recaptcha)、邮箱验证注册、公告、附件上传([image:]/[file:] 标签渲染)。 ## 3. 阶段划分(每阶段验证 + commit,可随时暂停) ### Phase 0 后端止损(≈半天,独立) - P0-1 删除 Web 更新链路(server.js /api/update/check + /api/update/run、admin.js 前端引用、cli.js zip 分支)→ 消除 RCE 面 + `.git` 覆盖风险 - P0-2 JWT_SECRET 启动生成随机值写入 `.env.json`(消除 R4 硬编码密钥) - P0-3 /api/setup/complete 加 adminOnly;/setup/status 移除 default_password(消除 R5 接管) - P0-4 /api/proxy/fetch 加 adminOnly + 私网地址过滤(消除 R3 SSRF) - P0-5 邮件验证码不回显 + 修复 pending 重建 bug(消除 R7) - 验证:curl 逐项(未登录 401、内网 URL 拒绝、响应无 code) ### Phase 1 后端安全加固(≈1-1.5 天) - P1-1 上传白名单 + /uploads 防护头(R1) - P1-2 内容净化:ssr.js + 后端出口统一 DOMPurify/转义(R2 服务端侧;前端侧随 v2 组件实现) - P1-3 登录/发帖限流 + 服务端验证码校验(R8,express-rate-limit) - P1-4 密码箱解锁限流 + PBKDF2 600k(M1) - P1-5 adminOnly 查库复查、草稿权限、错误信息收敛、rejectUnauthorized 收敛、avatar 白名单(M2-M7 中后端项) - P1-6 cli.js 统一到 db.js(消除双封装 + data.db 路径分裂) - P1-7 schema_version 迁移框架(幂等补列 + PRAGMA user_version) - 验证:curl 安全用例 + `node cli.js status/config/password` 正常 ### Phase 2 数据层换轨 better-sqlite3(≈1 天,依赖 P1-6/P1-7) - 前置:Node 升 22 LTS(宝塔 Node 版本管理器);README/Docker 示例同步 - db.js:`new Database(DB_PATH)` 同步初始化;run/get/all 重写(prepare + info.lastInsertRowid);删 saveDb/export;initTables 保留幂等补列 - routes/import.js:上传文件落临时路径只读打开 - 数据零迁移:现有 data/rainweb.db 直接打开;`PRAGMA integrity_check` 预检 - 验证:备份 → 启动 → CRUD 走查 → cli 命令 → sqlite3 命令行直查 ### Phase 3 前端工程化搭建(≈1 天) - 项目根新建 `frontend/`(Vite + React + React Router;多入口:`index.html`(前台)+ `admin.html`(后台)) - 共享层:api 客户端(封装现有 /api/*,token 仍 localStorage,错误处理统一)、工具(escapeHtml/日期/分页)、主题(深浅色状态管理) - `style.css` 迁入前台入口;`${site_name}` 等占位符保留在构建模板中(serveIndex 运行时替换机制不变) - Vite 配置:构建产物输出到 `public/dist/`;`base: '/'`;多入口 rollupOptions - package.json scripts:`dev`(vite)、`build`(vite build)、`start`(server.js) - 验证:dev server 起得来、两个入口都能打开、HMR 正常 ### Phase 4 前台页面迁移(≈3-4 天,核心工作量) 按页面迁移为 React 组件,**视觉逐页对照还原**: 1. 布局壳(导航栏/主题切换/壁纸/磨砂玻璃)+ React Router 路由表(/、/blog、/forum、/passwords、/login、/register、/profile、/write、/forum-manage、/embed、/setup);导航栏「管理后台」按钮 = 整页跳转 `/admin`(``,不走 SPA 路由) 2. 首页(瀑布流、侧栏头像/简介、最新文章)→ 原 HOMEPAGE 逻辑 3. 博客(列表/详情/编辑,markdown + [image:]/[file:] 渲染 → 组件化 DOMPurify 净化) 4. 论坛(分类/子分类/发帖/回复/详情) 5. 密码管理器(PIN 解锁、加密交互,见 §4.4) 6. 登录/注册(验证码、邮箱验证流程) 7. 个人中心(头像上传、资料编辑) 8. 音乐嵌入、公告、其他全局组件 - 验证:逐页对照 v1 截图/行为走查;无控制台报错 ### Phase 5 后台独立应用(≈2 天) - MUI 后台(/admin):完全独立入口与路由;入口方式 = 前台导航「管理后台」按钮整页跳转(Phase 4 已建);后台内可返回前台(跳转 /) - 登录态守卫(未登录跳转 /login,JWT 与前台共用);布局(侧栏导航 + 顶栏) - 页面:仪表盘、站点设置(含主题/壁纸/玻璃参数)、博客管理、论坛管理、用户管理、公告、面板链接(嵌入 + proxy 代理保留)、验证码/邮件配置、上传管理、密码箱(admin 视角)、更新检查入口移除(P0-1 已删) - 原 admin.js 600 行的逻辑按 MUI 组件重写 - 验证:后台全功能走查 + 前台联动(改设置 → 前台生效) ### Phase 6 集成上线(≈1 天) - server.js:静态服务指向构建产物;SPA fallback 分流(/admin* → 后台入口,其余 → 前台入口);serveIndex 占位符对构建产物生效 - 旧 public/*.html 与 public/js/ 全部退役删除(ssr.js 引用除外——核对 ssr.js 是否引用 style.css/占位符,保留所需) - SEO 双轨验证:/blog/:id、/forum/:id、sitemap.xml、robots.txt 行为不变 - 部署流程更新:宝塔 = npm install → npm run build → npm start - README/AGENTS.md 全量更新(v2 架构、命令、构建链说明) ## 4. 关键技术决策 ### 4.1 TypeScript? 默认**不用 TS**(v1 全 JS,单人无测试,减少迁移摩擦);如用户要 TS 可启用(React + Vite TS 模板),代价是迁移工作量 +20%。→ 计划默认 JS,待确认。 ### 4.2 构建产物与占位符 Vite 构建产物 index.html 保留 `${site_name}`/`${site_description}`/`${site_favicon}` 文本,serveIndex 运行时替换机制不变(构建模板中写占位符即可)。后台入口同理。 ### 4.3 路由与 fallback - 前台:React Router(history 模式),server.js `app.get('*')` 回前台入口 - 后台:/admin 前缀路由,server.js 增加 `/admin*` → 后台入口(注意在 SPA catch-all 前) - SSR 路由(/blog/:id、/forum/:id)优先级高于 SPA fallback(现状已如此,保持) ### 4.4 密码管理器加密 v1 为"服务端保管密钥"模型(PIN 明文到服务端派生)。v2 前台重写时**默认保持行为不变**(服务端派生 + PBKDF2 600k,Phase 1 已加固)。真正 E2E(WebCrypto 客户端派生)列为 v2 后续可选项,不在本次范围。 ### 4.5 音乐嵌入 v1 的 music-embed(自动隐藏、位置、超时)迁移为 React 全局组件,行为参数从 site_settings 读取,逻辑照搬。 ### 4.6 验证码 captcha.js 前端逻辑(内置 SVG 验证码 + recaptcha)React 化;服务端校验在 Phase 1 已接通(P1-3)。 ## 5. 验证策略(无测试环境) - 每阶段:curl API 用例 + 浏览器手动走查 + `node cli.js` 命令 - Phase 4/5:逐页对照 v1 行为清单(§2 保留功能点逐项打勾) - 上线前:完整回归清单(登录/发帖/上传/密码箱/主题/面板嵌入/SEO 直链) - 可选:引入 Vitest + React Testing Library 对共享层(api 客户端、渲染函数)补少量单测——默认不做,待确认 ## 6. 风险与回滚 | 风险 | 缓解 | |---|---| | 前端重写回归(11 页功能面广) | 阶段化推进、§2 功能清单逐项走查;v1 代码保留到 Phase 6 验收通过再删 | | 密码管理器迁移出错 | 加密逻辑独立模块化迁移,Phase 4 单独验收 | | better-sqlite3 换轨 | 数据零迁移 + 备份 + PRAGMA 预检;失败可随时回滚 db.js(v1 代码在 git 历史) | | 构建链引入部署变化 | Phase 6 单独验收部署流程;dev(vite dev)+ prod(build)双路径文档化 | | SEO 回归 | ssr.js 双轨不变,Phase 6 专门验证直链 | ## 7. 工时总览 | 阶段 | 内容 | 工时 | |---|---|---| | Phase 0 | 后端止损 | 0.5 天 | | Phase 1 | 后端安全加固 + cli 统一 + 迁移框架 | 1-1.5 天 | | Phase 2 | better-sqlite3 换轨 | 1 天 | | Phase 3 | 前端工程化搭建 | 1 天 | | Phase 4 | 前台页面迁移 | 3-4 天 | | Phase 5 | 后台独立应用(MUI) | 2 天 | | Phase 6 | 集成上线 + 文档 | 1 天 | | **合计** | | **9.5-11.5 天** | 每阶段结束:验证清单通过 → git commit → 可暂停验收。