Files
dusuniot/docs/admin-crm.md
T

90 lines
7.1 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.
# 后台(Admin / CRM)与 MCP 说明
> v0.13.0 起:前台导航修复(loader 服务函数化)、全站图片占位图 + 懒加载、favicon。
> v0.12.0 起:PG 16 → 18.6(增量备份能力)、备份系统(全量/增量/S3)、用户权限分层。
> v0.11.0 起:后台按「功能接近原版 WordPress + 现代化 CRM 界面」重做一轮,并新增站点管理 MCP 服务器。
## 前台约定(v0.13.0 起生效)
- **TanStack Start loader 是同构运行的**:客户端导航(点击 LOGO / `<Link>` / 分页)会在浏览器重跑一遍
loader。凡直接调用 `db`/查询层的写法(依赖 `bun:sql`,客户端是 stub)全部失败,页面退化为空数据。
**loader 的数据获取必须走 `createServerFn`**(服务端执行返回纯 JSON);`redirect()/notFound()` 不能在
serverFn 内抛给 Router,用协议标记(如 `$.tsx` 的 `__redirect/__notFound`)回传后由 loader 本地抛出。
已改造:`loadHomePage`(/)、`loadCatchAll`(/$)、`loadProduct`、`loadCollectionCategory`、`loadShopData`、
`loadSearchData`、`loadContactData`、`loadBlogPost`、`loadSolutionPage`、`loadBlogArchive`、`loadSolutionArchive`、
`loadCollection`(/collection/)等;购物车/结账/账户本来就用 serverFn(getCart/getCurrentUser/getMyOrders)。
- **图片占位图与懒加载**:`public/uploads/placeholder.jpg`(灰底 + 低透明度 LOGO,300×260,ImageMagick 生成);
全部前台 `<img>` 由 Layout 内联脚本补 `loading="lazy" decoding="async"`(MutationObserver 覆盖新增节点),
加载完成前显示占位背景(`app.css` 的 `.ds-site img` 规则;作用域为 Layout 的 `<main class="ds-site">`)。
注意透明 PNG 加载完成后会透出占位图——导出透明图时慎用。
- **缺失图片补齐**:`bun run scripts/sync-missing-uploads.ts` 幂等——扫库(contents/products/media)引用路径,
与 public/uploads 比对,缺失文件从原站下载(v0.13.0 补回 90 张;原站已失效 38 张不可恢复,走占位图)。
- **favicon**:`public/favicon.ico`(原站 32×32 PNG 转 ICO,ImageMagick)+ `apple-touch-icon.png`(LOGO 180×180),
根路由 `head().links` 注入。
- **导航宽度**:Header 顶栏与主导航行统一 `max-w-[1400px] mx-auto` 居中(2026-11-04 用户指定,原站基准)。
## 用户权限分层(RBAC)
两类用户:**普通用户**(customer,仅商城账号)与**后台用户**(admin > manager > editor)。能力矩阵(`src/server/auth.ts` requireCapability):
| 能力域 | 允许角色 | 覆盖操作 |
| --- | --- | --- |
| content | admin/manager/editor | 内容保存/删除、修订恢复、媒体上传/编辑、菜单项、筛选、重定向 |
| commerce | admin/manager | 产品保存/删除、订单状态、询盘状态 |
| system | admin | 用户管理、系统设置、语言、备份、审计日志查看 |
用户页 `/admin/users/` 提供「全部 / 后台用户 / 普通用户」Tab。
## 备份系统(PostgreSQL 18 物理备份)
- PG 已升级 **16.15 → 18.6**(容器 `dusuniot-pg`,`summarize_wal=on`,命名卷 `dusuniot-pg18-data`,`--restart unless-stopped`;旧 16 容器保留为 `dusuniot-pg16-old` 可回滚)
- 全量:`pg_basebackup -Fp -Xs` → `backups/pg/full-<ts>/`
- 增量:`pg_basebackup --incremental=<最近备份>/backup_manifest`(PG 17+ 能力;实测全量 124MB → 增量 5.4MB)
- 归档:每次备份 tar.gz → `backups/artifacts/`;配置 S3 后上传(Bun.S3Client,支持 multipart 大文件)
- 保留:保留最近 N 个全量链(该全量及其后全部增量),本地与 S3 同步清理
- 恢复:`pg_combinebackup 全量 增量…` 合并 → 作为 PGDATA 启动(已在容器内实测恢复 699 内容完整)
- 定时:settings.backup.schedule 开启后,jobs worker(`bun scripts/jobs-worker.ts`)按间隔执行 `backup.run`(自动增量、无备份时全量),完成后自排下一轮
- UI:`/admin/backups`(仅 admin):立即全量/增量、本地+S3 列表、删除、S3/保留/定时配置
## 后台功能清单(/admin,React + Ant Design)
| 模块 | 路由 | 能力 |
| --- | --- | --- |
| Dashboard | `/admin/` | KPI 卡(30 天环比:订单/营收/新询盘)、近 30 天订单/询盘/营收三趋势图、询盘漏斗(new/read/replied/spam/archived 占比)、最近订单 + 最新询盘、快捷入口 |
| 页面 / 文章 | `/admin/contents/` | page/post/landing Tab、搜索、分页、删除;编辑页支持 **分类目录/标签绑定**(content_terms)、**Elementor JSON** 编辑(meta.elementor,前台 `/slug/` 通栏渲染)、**修订历史**(保存自动留档、查看/恢复)、已发布页面前台预览链接 |
| 菜单 | `/admin/menus/` | menus 4 个位置(menu-1/menu-2/max_mega_menu_1/max_mega_menu_2)+ menu_items 树编辑(父级/排序/新窗口),前台 Header/Footer 即时读取 |
| 媒体库 | `/admin/media/` | 列表/搜索/预览、alt 与标题编辑、**上传**(≤20MB,写入 uploads/YYYY/MM/,自动解析 PNG/JPEG/GIF/WebP 宽高) |
| 产品 | `/admin/products/` | CRUD + 属性/分类/特色图/图集 |
| 订单 | `/admin/orders/` | 列表/详情/状态流转 |
| 询盘 | `/admin/inquiries/` | 状态 Tab、关键字、详情抽屉、跟进流转(new→read→replied) |
| 语言 | `/admin/languages/` | 启用开关 |
| SEO / 重定向 | `/admin/seo/` | 重定向 CRUD(301/302/正则) |
| 筛选 | `/admin/filters/` | 前台产品筛选器配置 |
| 用户 | `/admin/users/` | 列表/搜索;admin 可新建用户、改角色、重置密码(最后一个 admin 防降级锁死) |
| 系统设置 | `/admin/settings/` | settings 表 kv JSON 编辑器(site/woocommerce/mail/seo),仅 admin 可保存 |
| 审计日志 | `/admin/audit/` | 全部后台写操作留痕(操作人/动作/实体/摘要),含 MCP 调用(actor 为空) |
规范:所有 server function 第一步 `requireAdmin()`;写操作落 `audit_logs`;图标全 SVG(lucide / antd icons)。
## MCP 服务器(dusuniot-cms)
- 入口:`mcp/server.ts`(Bun 直跑,stdio JSON-RPC,MCP 2024-11-05,无 SDK 依赖)
- 注册:`.zcode/config.json`(workspace 级,会话启动自动连接)
- 直连 PostgreSQL(`DATABASE_URL`,默认 `postgres://dusuniot:dusuniot@127.0.0.1:25432/dusuniot`),仅限受信任本机;写操作落审计日志(actor 为空 = MCP)
- 工具(17 个):
- `dashboard_stats` 看板统计
- `list_contents` / `get_content` / `create_content` / `update_content` / `delete_content`(自定义单页面:type=page + elementorJson,保存/更新自动留修订快照,slug 冲突自动加后缀)
- `list_revisions` / `restore_revision`
- `list_media` / `upload_media`(base64,≤20MB,自动解析宽高)
- `list_products` / `list_orders` / `update_order_status`
- `list_inquiries` / `update_inquiry_status`
- `get_setting` / `set_setting`
## 手动测试
```sh
bun mcp/server.ts # stdio;initialize → tools/list → tools/call
bun test # 11 pass
bun run build && bun scripts/prod-server.ts # 站点 + 后台 :3312
```