- /admin/settings 弃用 JSON 编辑器改 antd Tabs 分组表单(site/woocommerce/mail/seo/security),未知键落「其他」JSON 兜底 - 登录安全:reCAPTCHA v2/v3 开关+密钥+阈值(siteverify fail closed),失败次数锁定;/admin 与 /my-account 登录接入 - 内容正文与产品详细描述换 TipTap v3:工具栏/Markdown 输入与导入/HTML 源码/图片上传/媒体库选图 - 根路由补 viewport meta(移动端根因);390px 实测 14 关键页 0 横向溢出 - 首页 Advance Tabs ≤767px 横滑、联系页内联 margin 块收缩、/shop 网格 4→3→2 列、移动菜单手风琴
9.9 KiB
9.9 KiB
后台(Admin / CRM)与 MCP 说明
v0.14.0 起:设置页 Tabs 表单 + 登录安全(reCAPTCHA/失败锁定)、TipTap 富文本编辑器(Markdown/媒体库)、前台移动端自适应(viewport + 溢出收敛)。 v0.13.0 起:前台导航修复(loader 服务函数化)、全站图片占位图 + 懒加载、favicon。 v0.12.0 起:PG 16 → 18.6(增量备份能力)、备份系统(全量/增量/S3)、用户权限分层。 v0.11.0 起:后台按「功能接近原版 WordPress + 现代化 CRM 界面」重做一轮,并新增站点管理 MCP 服务器。
系统设置与登录安全(v0.14.0)
/admin/settings弃用整键 JSON 编辑器,改为 antd Tabs 分组表单:站点信息 / 商城配置 / 邮件配置 / SEO / 登录安全;保存时与现有 JSON 合并(表单未覆盖的字段保留)。 无表单定义的键(backup 等专属页管理的除外)落在「其他」Tab 仍以 JSON 编辑兜底。- 登录安全(settings 表 key=security,
src/server/security.ts):- reCAPTCHA 开关 + 版本(v2 复选框 / v3 隐形评分)+ Site/Secret Key + v3 阈值;
开启后
/admin与/my-account登录均需通过 Google siteverify(6s 超时,fail closed), 前端组件src/components/admin/Recaptcha.tsx(未开启不注入 Google 脚本)。 - 登录失败锁定:同邮箱连续失败 ≥ 上限(默认 10)锁定(默认 15 分钟);进程内存计数,重启清零。
- 公开配置经
getLoginSecurityPublic下发(仅 enabled/version/siteKey,Secret 不回传)。
- reCAPTCHA 开关 + 版本(v2 复选框 / v3 隐形评分)+ Site/Secret Key + v3 阈值;
开启后
富文本编辑器(v0.14.0)
- 内容编辑页(正文)与产品编辑页(详细描述)换 TipTap v3(
src/components/admin/RichEditor.tsx):- 工具栏:撤销重做 / 标题 H2-H4 / 加粗斜体下划线删除线行内代码 / 列表 / 引用 / 分隔线 / 代码块 / 链接 / 图片 / 表格 / 清除格式 / HTML 源码切换;
- Markdown:输入即时转换(
##→H2、**加粗、-列表等 input rules)+「Markdown 导入」 弹窗(marked 解析,可插入光标处或替换正文); - 媒体库:图片按钮本地上传(
uploadMediaFile→ /uploads/YYYY/MM/)或「媒体库选图」弹窗 (MediaPickerModal,搜索/分页/缩略图); - antd Form 受控(value/onChange),SSR 需
immediatelyRender: false(已内置)。
- 编辑器样式
src/styles/admin-editor.css(仅.rich-editor作用域,随组件 import)。
前台移动端自适应(v0.14.0)
- 根路由补
<meta name="viewport">——此前缺失导致手机按 ~980px 布局再缩小,是「移动端没有」的根因。 - 溢出收敛(390px 实测 14 个关键页全部 0 横向溢出,
scripts外的诊断脚本见 /tmp):- 首页 Elementor Advance Tabs 横向标签条 ≤767px 改横滑(
min-width: max-content+ overflow-x); - 内容模板
width:100%+左 margin 的内联信息块(联系页地址等)≤767px 收缩为自适应; - /shop/ 产品网格 4→3(≤1024)→2(≤767)列;
content-html iframemax-width 100%。
- 首页 Elementor Advance Tabs 横向标签条 ≤767px 改横滑(
- Header 移动端菜单改手风琴(顶级项可跳转 + 箭头展开子菜单,默认收起)。
前台约定(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_revisionlist_media/upload_media(base64,≤20MB,自动解析宽高)list_products/list_orders/update_order_statuslist_inquiries/update_inquiry_statusget_setting/set_setting
手动测试
bun mcp/server.ts # stdio;initialize → tools/list → tools/call
bun test # 11 pass
bun run build && bun scripts/prod-server.ts # 站点 + 后台 :3312