Files

103 lines
6.5 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.
# DusunIoT 重建版(TanStack Start + Bun + PostgreSQL)
将原 WordPress + Elementor + WooCommerce + GTranslate 站点(dusuniot.com)重构为单体应用:
前台 SSR 1:1 还原、后台 React + Ant Design 功能等价实现、PostgreSQL 关系型数据模型。
> 方案文档:`docs/dusuniot-rebuild-tanstack-bun-pg-v2.md`
## 技术栈
| 领域 | 选型 |
| --- | --- |
| 运行时 / 包管理 | Bun 1.4+ |
| 前台 SSR / 路由 | TanStack Start(Vite)+ React 19 + TS |
| 数据库 | PostgreSQL 16(Bun.sql + Drizzle ORM) |
| 后台 UI | React + Ant Design 6(**仅 SVG 图标**,禁 emoji/图标字体) |
| 后台任务 | jobs 表持久化队列(`scripts/jobs-worker.ts`,独立进程) |
## 快速开始
```sh
bun install
# .env 默认 DATABASE_URL=postgres://dusuniot:dusuniot@127.0.0.1:25432/dusuniot
bun run db:migrate # 应用迁移(src/db/migrations)
bun run import:wordpress # 全量导入 WP 备份库(需 MariaDB 容器 dusuniot-mariadb, 端口 13306)
bun run dev # 开发服务器 http://localhost:3311
bun run build && bun run start # 生产构建(Nitro .output)
bun run scripts/jobs-worker.ts # 后台任务 worker
bun test # 单元/集成测试
```
## WordPress 数据迁移
- 备份源:`dusuniot-full-20261029.tar.gz`(站点文件 + mysqldump)。媒体已硬链接到 `public/uploads`。
- 导入脚本:`scripts/wordpress-import/import.ts`,支持 `--only=step1,step2` 分步重跑(步骤:reset/media/users/categories/attributes/products/contents/views/orders/flamingo/elementor/forms/menus/filters/redirects/languages/final)。
- 导入规模:148 产品(含属性/筛选映射)、674 内容(含 Elementor JSON)、53,101 询盘(Flamingo + Elementor 双源)、108 订单、8,210 媒体、493 条 301 重定向、104 语言、4 菜单 283 菜单项。
- 旧 ID 映射存 `legacy_id_mappings` 表;WP 旧密码(phpass $P$)保留在 `users.legacy_password_hash`,客户登录时透明升级 bcrypt。
## 与原站插件的功能等价映射
| 原插件 | 新实现 |
| --- | --- |
| WooCommerce | products/orders/order_items/payments 关系模型 + 购物车/结账/账户(PayPal 回调位预留,幂等键 transaction_id) |
| Contact Form 7 + Flamingo | inquiry_forms(表单定义)+ inquiries(统一询盘表)+ 邮件任务队列 |
| Filter Everything | filters 配置表 + product_attributes/values/map 关系型筛选(复合索引 + EXISTS 交集查询) |
| GTranslate | /`<lang>`/ 前缀路由 + UI 壳层字符串 + content/product_translations 真实发布版本(缺翻译不生成伪语言页) |
| Redirection | redirects 表 + 请求中间件(301/302,支持正则) |
| Elementor(前台) | src/components/elementor/Renderer.tsx(section/column/heading/text-editor/image/button/image-box/icon-list/tabs/toggle 等 20+ widget) |
| Rank Math SEO | contents/products 内置 SEO 字段 + sitemap.xml + robots.txt + hreflang |
| WP Rocket | 设计上按 URL/语言做服务端缓存(Cloudflare/Nginx 层),登录态/购物车禁共享缓存 |
| Dusun Flamingo Reader | 后台询盘模块 + REST API(保留给 AI 线索管道) |
## URL 兼容(SEO 硬性要求)
- 页面 `/<slug>/`、文章 `/<category>/<slug>/`、产品 `/product/<slug>/`、产品分类 `/collection/<slug>/`(与原站 permalink 一致,trailingSlash always)。
- 493 条旧重定向规则原样生效;canonical/hreflang/sitemap 由 SEO 模块输出。
## 后台
`/admin`(默认管理员见导入输出)。模块:Dashboard / 内容 / 产品 / 订单 / 询盘 / 媒体 / 语言 / SEO 重定向 / 筛选 / 用户 / 设置。
所有接口 `requireAdmin()` 权限校验,敏感操作写 `audit_logs`。
## Docker 部署(v0.15.0)
生产环境部署在 OVH(OVH-US-BAK)`/home/docker/dusuniot/`,域名 `dusuniot.ibug.qzz.io`(Cloudflare 橙云):
```
/home/docker/dusuniot/
├── docker-compose.yml # 即仓库 deploy/docker-compose.yml
├── app/ # 仓库源码 rsync(.dockerignore 排除 node_modules/dist/uploads 等)
└── data/
├── pg/ # PostgreSQL 18 数据卷
└── uploads/ # 媒体库(容器内双挂载:/app/public/uploads 写入 + /app/dist/client/uploads 服务)
```
- 应用容器 `dusuniot-app`(oven/bun 构建,`bun scripts/prod-server.ts`,PORT 3312),仅绑定 `127.0.0.1:3320`;数据库容器 `dusuniot-db-1`(postgres:18,不对外暴露)。
- nginx 站点 `/etc/nginx/sites-available/dusuniot.ibug.qzz.io.conf`:80 + 443(Let's Encrypt,certbot webroot 续期自动 reload)→ `proxy_pass http://127.0.0.1:3320`。CF SSL 模式 Full/Full(strict)/Flexible 均兼容。
- 数据迁移:本机 `pg_dump -Fc` → 服务器 `pg_restore`;媒体经 tar+zstd 流式同步到 `data/uploads`。
- 更新发布:rsync 源码后 `cd /home/docker/dusuniot && docker compose up -d --build app`。
- `scripts/prod-server.ts` 的 `/uploads/*` 运行时直读磁盘(媒体上传后无需重启即可访问,本地裸跑同样受益)。
## v0.16.0 升级要点(后台体验)
- **数据清洗(生产必跑一次)**:询盘表存量 WordPress PHP 序列化串还原为 JSON/纯文本
(productInterest → 逗号连接、fields/utm 递归还原)。幂等,重复执行零更新:
`bun scripts/cleanup-php-serialize.ts`(先 `--dry` 核对)。
- **数据库迁移**:`users` 新增 avatar / locale / theme / mcp_token 四列(0001_user_profile.sql)。
- **后台 i18n**:默认英文,词典 `src/admin-i18n/locales/en.ts`(键=中文源串);
偏好存 localStorage(admin_locale / admin_theme)。新增语言时注册词典并在
`src/admin-i18n/shared.ts` 的 ADMIN_LOCALES 加选项;`tests/admin-i18n.test.ts` 强制 en 全覆盖。
- **主题/字号**:antd 主题 token 改动(fontSize 15、深色算法)后需重跑 `bun scripts/gen-antd-css.tsx`。
- **MCP 令牌**:个人设置页生成 `users.mcp_token`;MCP server 以
`DUSUN_MCP_TOKEN=<token> bun mcp/server.ts` 启动即校验(角色须在权限管理中允许 MCP)。
- **关站**:设置 → 关闭网站(settings.maintenance),前台 503 维护页,/admin 不受影响,
配置读取缓存 60s。
## 目录结构
见方案文档第 6 节。`src/server/*` 按业务域拆分(auth/content→data/products→data/filters/orders→commerce/inquiries/translations/seo/jobs)。
## 版本
版本号以 `package.json` `version` 为准,每轮交付自增(patch/minor/major)。