后台管理系统(admin 管理端)项目说明书
项目根目录:
w:\AI-Pet-Project\xhs-miniapp-saas管理端代码目录:admin/;后端管理 API 代码目录:backend/app/routers/admin.py、backend/app/services/admin_service.py、backend/app/models/admin.py等 线上地址:https://admin.jvguang.com(仅内网 WiFi 可访问,公网返回 403)
1. 项目概述
后台管理系统是「小红书 SaaS 多租户内容运营平台」的管理控制台,用于平台运营方(Admin)对入驻商家(Merchant)、平台规则(RAG 知识库)、LLM 模型配置、AI 聊天会话与记忆进行统一管理。
核心定位:
- 运营侧一站式管理:用户(商家)管理、平台规范管理、公司知识库管理、模型配置热切换、全局知识库、AI 记忆库、会话管理(人工客服接管)。
- 与小程序端、Web 端共享同一套后端 API 与数据库(PostgreSQL),通过 RLS(Row Level Security)行级隔离 + Admin 专用无 RLS 数据库会话 实现双模式访问。
- 安全要求(硬性约束):仅内网可访问、所有页面与接口返回
noindex, nofollow, noarchive响应头防止搜索引擎收录、页面标题为「后台管理系统」且不含任何「小红书 / XHS」字样。
注意:本文档中的"管理端"指的是 admin/ 前端 + 后端 /api/admin/* 路由族;其余租户端(小程序/Web)功能不在本文档范围内,但管理端会跨租户查看这些端产生的数据(文章、聊天、记忆、知识库等)。
2. 技术栈
| 层次 | 技术 | 说明 |
|---|---|---|
| 前端框架 | React 18 + TypeScript 5 | admin/ 目录 |
| UI 组件 | Ant Design 5 (antd ^5.16) + @ant-design/icons | 表单/表格/抽屉/消息提示 |
| 路由 | react-router-dom v6 | BrowserRouter + 手写 RequireAuth 守卫 |
| HTTP | axios ^1.6 | 统一拦截器,自动注入 Authorization: Bearer |
| 构建 | Vite 5 | dev 代理 /api 到后端 8000 端口 |
| 样式 | 自定义 editorial.css | 编辑部风格(editorial)视觉体系 |
| 后端框架 | Python FastAPI + asyncpg + pgvector | /api/admin/* 路由族 |
| 数据库 | PostgreSQL 16 + pgvector 扩展 | 17 张表,10 张租户表启用 RLS |
| 部署 | Nginx(HTTPS)→ uvicorn(FastAPI :8000) | backend/deploy/nginx-admin-intranet.conf |
3. 整体架构图
flowchart TB
classDef net fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef mw fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20
classDef svc fill:#f3e5f5,stroke:#6a1b9a,stroke-width:2px,color:#4a148c
classDef db fill:#fff8e1,stroke:#ef6c00,stroke-width:2px,color:#e65100
ADMIN_BROWSER["🖥️ 管理员浏览器<br/>https://admin.jvguang.com"]
NGINX["🛡️ Nginx · 443 SSL"]
INTRANET_MW["✅ AdminIntranetMiddleware<br/>内网IP白名单 + noindex"]
ADMIN_ROUTER["📦 routers/admin.py"]
AUTH["🔑 /api/admin/login<br/>写死账号签发 admin JWT"]
ADMIN_SVC["⚙️ admin_service.py<br/>dashboard/CRUD/配置缓存/热切换"]
CHAT_SVC["💬 chat_service.py<br/>全局知识库/记忆/会话"]
CHAT_WS["🔌 chat_ws.py<br/>AI自动回复/人工客服"]
ENC["🔐 encryption.py<br/>Fernet 加密APIKey"]
USERS["👥 merchants / merchant_profiles"]
RULES["📏 platform_rules (无RLS)"]
KNOW["📚 merchant_knowledge_chunks (RLS)"]
LLM_CFG["🧠 llm_function_configs / cover_ai_configs (无RLS)"]
CHAT_TB["💬 chat_conversations / chat_messages /<br/>chat_memory_docs (RLS)"]
GLOBAL["🌍 global_knowledge_docs (无RLS)"]
COVER_TB["🎨 cover_projects / cover_images /<br/>cover_styles / cover_covers (RLS)"]
ADMIN_BROWSER -->|"443 HTTPS"| NGINX
NGINX -->|"proxy_pass 127.0.0.1:8000"| INTRANET_MW
INTRANET_MW --> ADMIN_ROUTER
ADMIN_ROUTER --> AUTH
ADMIN_ROUTER --> ADMIN_SVC
ADMIN_ROUTER --> CHAT_SVC
ADMIN_ROUTER --> CHAT_WS
ADMIN_SVC --> ENC
ADMIN_SVC -->|"AdminDb"| USERS
ADMIN_SVC -->|"AdminDb"| RULES
ADMIN_SVC -->|"AdminDb"| KNOW
ADMIN_SVC -->|"AdminDb + Fernet"| LLM_CFG
ADMIN_SVC -->|"AdminDb"| COVER_TB
CHAT_SVC -->|"AdminDb"| GLOBAL
CHAT_SVC -->|"AdminDb"| CHAT_TB
CHAT_WS --> CHAT_TB
class ADMIN_BROWSER,NGINX net
class INTRANET_MW mw
class AUTH,ADMIN_ROUTER,ADMIN_SVC,CHAT_SVC,CHAT_WS,ENC svc
class USERS,RULES,KNOW,LLM_CFG,CHAT_TB,GLOBAL,COVER_TB db图例:🟦 蓝 = 接入层 · 🟩 绿 = 安全中间件 · 🟪 紫 = 后端服务 · 🟧 橙 = 数据库表(底部横向排布,经 AdminDb 无 RLS 跨租户访问)
关键隔离模型:
- 商家/租户端访问走
DbSession(deps.py注入app.current_merchant_id会话变量,触发 RLS 策略)。 - Admin 端访问走
AdminDb(deps.py::get_admin_db),不注入 RLS 上下文,依赖CurrentAdmin(role=admin JWT)保证只有管理员可用,实现跨租户全量读写。 platform_rules、llm_function_configs、cover_ai_configs、global_knowledge_docs四张表故意不启用 RLS(全局共享)。
4. 目录结构总览
admin/
├── index.html # Vite 入口 HTML(标题:后台管理系统)
├── package.json / package-lock.json
├── tsconfig.json
├── vite.config.ts # dev 代理 /api → http://127.0.0.1:8000
├── .gitignore
└── src/
├── main.tsx # React 挂载入口
├── App.tsx # 路由表 + RequireAuth 登录守卫
├── vite-env.d.ts
├── api/
│ ├── client.ts # axios 实例 + token 存取(记住我)
│ ├── admin.ts # 全部 /api/admin/* 接口封装
│ └── types.ts # 接口 TS 类型定义
├── components/
│ └── MessageBridge.tsx # antd message 桥接组件
├── hooks/
│ └── useMessage.ts # 非组件环境获取 message 的 hook
├── layouts/
│ └── AdminLayout.tsx # 侧边栏 + 顶栏 + 内容区布局
├── pages/
│ ├── Login.tsx # 登录页
│ ├── Dashboard.tsx # 仪表盘
│ ├── Users.tsx # 用户(商家)管理
│ ├── Rules.tsx # 平台规范管理
│ ├── KnowledgeBase.tsx # 公司知识库管理
│ ├── ModelConfig.tsx # 模型配置(LLM 功能级 + 封面 AI)
│ ├── GlobalKnowledge.tsx # 全局知识库管理
│ ├── MemoryDocs.tsx # AI 记忆库管理
│ └── ChatSessions.tsx # 会话管理(人工客服)
├── styles/
│ └── editorial.css # 编辑部风格全局样式
└── utils/
└── messageBridge.ts # message API 桥接(脱离 React 上下文)5. 前端文件详解
5.1 入口与配置
| 文件 | 作用(控制的功能) | 关联文件 | 影响 |
|---|---|---|---|
index.html | 页面骨架;<title> 为「后台管理系统」,不出现「小红书/XHS」字样;引入字体与根样式 | src/main.tsx | 修改标题影响浏览器标签与 SEO 标题 |
vite.config.ts | dev 服务器配置;server.proxy['/api'] 指向 http://127.0.0.1:8000,解决开发跨域 | .env(后端) | 改代理目标影响本地联调后端地址 |
src/main.tsx | React 18 挂载 App 到 #root | src/App.tsx | 挂载点 |
src/vite-env.d.ts | Vite 环境变量类型声明 | 全局 | — |
5.2 路由与全局守卫
| 文件 | 作用 | 关联文件 | 影响 |
|---|---|---|---|
src/App.tsx | 定义全部路由:/login 公开;/ 及其子路由(dashboard/users/rules/knowledge/model/global-knowledge/memory-docs/chat-sessions)包裹在 RequireAuth 守卫内;* 重定向到 /dashboard | api/client.ts(getToken)、layouts/AdminLayout.tsx、全部 pages | 新增页面需在此注册路由;守卫逻辑影响整个后台的访问控制 |
src/layouts/AdminLayout.tsx | 后台主框架:可折叠侧边栏(8 个导航项:仪表盘/用户管理/平台规范/公司知识库/模型配置/全局知识库/AI 记忆库/会话管理)、品牌区「管理 Admin Console」、顶栏退出按钮;内容区渲染 Outlet | 全部 pages、api/client.ts(clearToken) | 导航菜单与布局改动影响所有管理页面的外观 |
5.3 API 层
| 文件 | 作用 | 关联后端 | 影响 |
|---|---|---|---|
src/api/client.ts | axios 实例(baseURL /api,60s 超时);请求拦截自动注入 Authorization: Bearer {token};响应拦截:401 清 token 并跳转 /login,其余错误统一 toast;Token 存取按「记住我」偏好分流到 localStorage/sessionStorage(key:xhs_admin_token / xhs_admin_remember) | 后端所有 /api/* | 改 baseURL/超时/拦截器会影响全部接口请求;token 存储策略影响登录持久性 |
src/api/admin.ts | 封装后端 /api/admin/* 全部接口(见下表) | backend/app/routers/admin.py | 新增后台功能需在此补充接口函数 |
src/api/types.ts | 定义接口请求/响应的 TypeScript 类型(AdminToken、User、Rule、LLMConfig、CoverAIConfig、GlobalKnowledgeDoc、MemoryDoc、AdminConversation、AdminMessage 等) | backend/app/models/admin.py、models/chat.py | 类型与后端 schema 不一致会导致编译错误或运行期数据缺失 |
admin.ts 中封装的接口函数与后端路由对应关系:
| 前端函数 | 后端端点 | 功能 |
|---|---|---|
login | POST /api/admin/login | 管理员登录(写死账号校验) |
getStats | GET /api/admin/stats | 仪表盘统计 |
listUsers / getUser / createUser / updateUser / deleteUser | GET /api/admin/users、GET/POST /api/admin/users、PUT/DELETE /api/admin/users/{id} | 商家 CRUD |
listRules / createRule / updateRule / toggleRule / deleteRule / reindexRules / uploadPlatformMarkdown | GET/POST /api/admin/rules、PUT/DELETE /api/admin/rules/{id}、PATCH .../toggle、POST .../reindex、POST .../upload | 平台规则 CRUD + 向量重建 + Markdown 上传 |
listUserKnowledge / uploadUserMarkdown / deleteUserKnowledge | GET /api/admin/users/{id}/knowledge、POST .../knowledge/upload、DELETE .../knowledge/{chunkId} | 公司知识库管理 |
getLLMConfig / updateLLMConfig / testLLM | GET/PUT /api/admin/llm/config、POST /api/admin/llm/test | 全局 LLM 配置(内存热切换) |
listLLMFunctionConfigs / updateLLMFunctionConfig / testLLMFunction | GET /api/admin/llm/function-configs、PUT .../{function_key}、POST /api/admin/llm/function-test | LLM 功能级配置(持久化到 DB) |
listCoverAIConfigs / updateCoverAIConfig | GET /api/admin/cover-ai/configs、PUT .../{function_key} | 封面 AI 配置 + 诊断 |
listGlobalKnowledgeDocs / create/update/deleteGlobalKnowledgeDoc / uploadGlobalMarkdown | /api/admin/chat/global-knowledge/docs*、/upload | 全局知识库管理 |
listMemoryDocs / deleteMemoryDoc | GET /api/admin/chat/memory/{merchantId}/docs、DELETE .../docs/{docId} | AI 记忆库管理 |
listConversations / listConversationMessages | GET /api/admin/chat/conversations、GET .../{merchantId}/messages | 会话列表/消息查看(跨租户) |
getAutoReplyStatus / toggleAutoReply | GET /api/admin/chat/auto-reply/status、POST .../toggle | AI 自动回复开关 |
sendAdminChatMessage / generateAdminChatDraft / clearConversation | POST .../conversations/{merchantId}/messages、.../ai-draft、.../clear | 人工客服发消息 / AI 起草 / 清空会话 |
5.4 消息提示体系(MessageBridge)
| 文件 | 作用 | 关联文件 | 影响 |
|---|---|---|---|
src/components/MessageBridge.tsx | 挂载在 App 根部的桥接组件:通过 App.useApp() 拿到 antd 的 message 实例,注入全局模块 | App.tsx、utils/messageBridge.ts | 移除该组件会导致全局 toast 失效 |
src/utils/messageBridge.ts | 导出全局 messageApi(模块级引用,非 React 上下文),供 axios 拦截器等非组件代码调用 | api/client.ts | — |
src/hooks/useMessage.ts | 提供 useMessage() hook,让页面组件在 React 上下文内安全获取 message 实例 | 各 pages | — |
5.5 页面详解
Login.tsx — 登录页
- 功能:管理员登录表单(账号+密码),调用
login(),成功后按「记住我」偏好存储 token 并跳转/dashboard;页面标题为「后台管理系统」。 - 关联:
api/client.ts(setToken/getRememberMe)、api/admin.ts。 - 影响:登录流程的入口;若后端
ADMIN_USERNAME/ADMIN_PASSWORD变更,此处无需改代码。
Dashboard.tsx — 仪表盘
- 功能:调用
getStats()展示平台总览(用户数、文章数、任务数等统计卡片)。 - 关联:
api/admin.ts、后端admin_service.dashboard_stats(查询 merchants/articles/tasks 等表 count)。 - 影响:数据口径由后端 SQL 决定。
Users.tsx — 用户(商家)管理
- 功能:商家列表(分页+手机号搜索)、创建/编辑/删除商家;手机号遵循
^1[3-9]\d{9}$,密码 8-64 位(与小程序/Web 统一规则);可查看单个商家的知识库详情。 - 关联:
api/admin.ts、models/admin.py(UserCreate/UserUpdate)、admin_service.create_user/update_user/delete_user(bcrypt 加密密码)。 - 影响:创建/修改商家直接影响登录体系;删除商家级联删除其文章/任务/图片/会话/记忆等全部数据(外键 ON DELETE CASCADE)。
Rules.tsx — 平台规范管理
- 功能:平台规则(限流词/发布规范/违禁词分类)CRUD、启停切换、向量重建(reindex)、Markdown 文件批量上传入库(
uploadPlatformMarkdown切块写入platform_rules)。 - 关联:
api/admin.ts、admin_service.list_rules/.../reindex_rules、rag/indexer.py(embedding 向量化)。 - 影响:规则是文章生成流水线
rag_search的召回来源(全局共享、无 RLS),修改直接影响所有商家生成文章的合规参考与内容。
KnowledgeBase.tsx — 公司知识库管理
- 功能:选择某个商家,查看其专属知识切片(
merchant_knowledge_chunks),支持上传该商家的 Markdown 规范文档(切块入库)与删除切片。 - 关联:
api/admin.ts、admin_service.list_user_knowledge/upload_user_markdown/delete_user_knowledge。 - 影响:商家知识库被文章生成的主题推荐与聊天 AI 回复使用;上传后通过
invalidate_merchant_knowledge_cache使该商家知识缓存失效(_knowledge_context.py)。
ModelConfig.tsx — 模型配置
- 功能:两大块——
- LLM 功能级配置(
/llm/function-configs):按 function_key(article_generate / compliance_check / title_tags / multimodal_kimi / multimodal_spark)配置 provider/model/api_key/base_url/temperature/max_tokens/is_enabled,持久化到数据库,保存后热生效(内存缓存刷新 +llm_client.reload())。 - 封面 AI 配置(
/cover-ai/configs):cover_vision / cover_text / cover_image 三个功能键,API Key 用 Fernet 加密(enc:v1:前缀)存储;含诊断面板(/cover-ai/diagnose)展示凭据来源、服务选择、环境变量是否配置等排障信息。
- 按项目约定:隐藏
cover_vision、cover_text编辑入口,突出multimodal_kimi为统一模型(cover_vision/cover_text自动回落到multimodal_kimi)。
- LLM 功能级配置(
- 关联:
api/admin.ts、admin_service.load_llm_function_configs_cache/get_function_config/update_llm_function_config、llm/client.py(LLMClientProxy 按 signature 失效重建 provider)、security/encryption.py。 - 影响:全局影响——模型配置变更会立即影响所有商家端(小程序/Web)的文章生成、合规检查、标题标签、封面神器等所有 AI 能力;改错 provider/api_key 可能导致全平台 AI 功能故障,因此提供 test 接口先行验证。
GlobalKnowledge.tsx — 全局知识库管理
- 功能:全局知识文档(
global_knowledge_docs,无 RLS,平台共享)CRUD + Markdown 上传(≤4000 字整篇存储,长文自动切片为 (i/N) 多篇)。 - 关联:
api/admin.ts、chat_service.list_global_knowledge_docs/upload_global_markdown。 - 影响:全局知识被注入到所有商家的聊天 system prompt(
chat_ai.build_system_prompt)与引导问题推荐;修改立即影响所有租户的 AI 助手回答。
MemoryDocs.tsx — AI 记忆库管理
- 功能:查看指定商家的聊天记忆文档(
chat_memory_docs,RLS 表但 Admin 跨租户访问),删除指定记忆。 - 关联:
api/admin.ts、chat_service.list_memory_docs_by_merchant/delete_memory_doc。 - 影响:记忆是聊天 AI 的长期上下文;删除记忆会让 AI 忘记该商家的历史偏好与承诺信息。
ChatSessions.tsx — 会话管理(人工客服)
- 功能:跨租户会话列表(以 merchants 表为主表 LEFT JOIN chat_conversations,保证所有商家都出现在列表,含无聊天记录的商家;支持 phone/company_name 模糊搜索);点击会话抽屉查看消息时间线(游标分页);AI 自动回复开关;人工客服接管:查看最新商家消息、AI 起草回复(
ai-draft,不落库)、编辑后发送(落库 + WS 推送sender_role=admin给商家);清空会话(删除消息 + 记忆 + 重置 last_msg_at)。 - 关联:
api/admin.ts、chat_service.list_conversations_admin/list_messages_by_merchant_admin/clear_conversation_admin、chat_ws.is_auto_reply_enabled/set_auto_reply_enabled/send_admin_message_to_merchant、chat_ai.generate_admin_reply_draft。 - 影响:人工客服功能是「AI 自动回复」的接管机制;发送消息会通过 WebSocket 实时推送到商家端聊天页;关闭自动回复后,商家消息不再触发 AI 回复。
5.6 样式
| 文件 | 作用 | 影响 |
|---|---|---|
src/styles/editorial.css | 编辑部(editorial)视觉风格:品牌区、侧边栏(ed-sider)、导航项(ed-nav-label/caption)、卡片、表格等全局样式 | 全站视觉;修改需注意与 antd 组件 class 的覆盖关系 |
6. 后端关联模块详解(管理端专属)
管理端依赖的
/api/admin/*路由族与相关服务,本文档只描述管理端直接使用到的部分。
6.1 路由:backend/app/routers/admin.py
管理后台 API 聚合入口,包含以下区块:
| 区块 | 端点 | 说明 |
|---|---|---|
| 登录 | POST /api/admin/login | secrets.compare_digest 恒时比较 ADMIN_USERNAME/ADMIN_PASSWORD,签发 role=admin 的 JWT;无注册入口 |
| 仪表盘 | GET /api/admin/stats | admin_service.dashboard_stats |
| 用户管理 | GET/POST /api/admin/users、GET/PUT/DELETE /api/admin/users/{id} | 商家 CRUD |
| 平台规则 | GET/POST /api/admin/rules、PUT/PATCH/DELETE /api/admin/rules/{id}、POST /reindex、POST /upload | 规则管理 + 向量重建 + Markdown 上传 |
| 公司知识库 | GET /api/admin/users/{id}/knowledge、POST .../knowledge/upload、DELETE .../knowledge/{chunkId} | 单商家知识管理 |
| 全局 LLM 配置 | GET/PUT /api/admin/llm/config、POST /api/admin/llm/test | 内存级热切换(factory.set_overrides) |
| LLM 功能级配置 | GET /api/admin/llm/function-configs、PUT .../{function_key}、POST /api/admin/llm/function-test | DB 持久化配置 + 测试 |
| 封面 AI 配置 | GET /api/admin/cover-ai/configs、PUT .../{function_key}、GET /api/admin/cover-ai/diagnose | 封面 AI 配置 + 排障诊断 |
| 全局知识库 | /api/admin/chat/global-knowledge/docs* + /upload | 全局聊天知识 CRUD |
| AI 记忆库 | GET /api/admin/chat/memory/{merchantId}/docs、DELETE .../docs/{docId} | 记忆管理 |
| 会话管理 | GET /api/admin/chat/conversations、GET .../{merchantId}/messages、POST .../{merchantId}/messages、POST .../ai-draft、POST .../clear、GET/POST /api/admin/chat/auto-reply/* | 跨租户会话/客服 |
6.2 服务:backend/app/services/admin_service.py
| 函数 | 功能 | 关键逻辑 |
|---|---|---|
list_users / get_user / create_user / update_user / delete_user | 商家 CRUD | 密码用 pwd_context.hash(bcrypt);手机号唯一约束;删除级联 |
list_rules / create_rule / update_rule / toggle_rule / delete_rule / reindex_rules | 规则 CRUD + 向量重建 | 新增/更新/重建时调 rag/indexer.py 生成 embedding(HNSW 向量索引) |
dashboard_stats | 仪表盘统计 | 跨表 COUNT(merchants/articles/tasks/chat 等) |
get_llm_config / update_llm_config / test_llm | 全局 LLM 内存热切换 | factory.set_overrides() + llm_client.reload();test 用临时 provider 验证连通 |
load_llm_function_configs_cache / get_function_config / update_llm_function_config / test_llm_function | LLM 功能级配置缓存与热更新 | 启动时(main.py lifespan)加载到内存;更新后 _refresh_cache_entry 刷新缓存并 llm_client.reload() |
load_cover_ai_configs_cache / get_cover_ai_config / update_cover_ai_config | 封面 AI 配置缓存 | api_key 写入时用 encrypt_secret Fernet 加密,读取时解密 |
upload_platform_markdown / upload_user_markdown / list_user_knowledge / delete_user_knowledge | Markdown 智能切块入库 | _split_markdown 按标题层级切块;user 知识写入 merchant_knowledge_chunks 并生成向量 |
6.3 安全中间件:backend/app/security/intranet.py
AdminIntranetMiddleware:拦截所有/api/admin/*请求——ADMIN_INTRANET_ONLY=true时校验客户端 IP 是否在ADMIN_ALLOWED_CIDRS(默认内网网段)内,否则 403INTRANET_ONLY;- 永远注入
X-Robots-Tag: noindex, nofollow, noarchive与X-Content-Type-Options: nosniff(防搜索引擎收录 + 防 MIME 嗅探); - 通过
ADMIN_TRUSTED_PROXIES信任 Nginx 的 X-Forwarded-For 获取真实 IP。
- 影响:该中间件是「后台仅内网访问」的第一道闸;生产环境建议再叠加 Nginx 层 IP 白名单(
deploy/nginx-admin-intranet.conf中allow/deny)。
6.4 模型:backend/app/models/admin.py
AdminLoginRequest/AdminTokenResponse:登录请求/响应。UserCreate/UserUpdate/UserDetailResponse/UserListResponse/UserKnowledgeListResponse:商家与知识切片 schema。RuleCreate/RuleUpdate/RuleListResponse/AdminRuleResponse/UploadResult:规则 schema。LLMConfigResponse/LLMConfigUpdate/LLMFunctionConfig/LLMFunctionConfigUpdate/LLMConfigListResponse/LLMFunctionTestRequest/LLMTestRequest/LLMTestResponse/CoverAIConfig/CoverAIConfigUpdate/CoverAIConfigListResponse/CoverAIDiagnoseResponse:模型配置 schema(models/admin.py与models/chat.py均含会话管理相关 schema:AdminConversationResponse、AdminMessageResponse、GlobalKnowledgeDoc*、MemoryDoc*、AutoReply*、AdminAiDraft*、ConversationClearResponse等)。- 约束:
UserCreate.phone匹配^1[3-9]\d{9}$、password8-64 位(与models/auth.py统一)。
6.5 依赖注入:backend/app/deps.py
CurrentAdmin:解析role=admin的 JWT,非 admin 返回 403。AdminDb:获取无 RLS 注入的数据库连接(管理员跨租户读写)。生产环境需使用BYPASSRLS数据库角色连接。
7. 数据库表关系(管理端视角)
erDiagram
merchants ||--o| merchant_profiles : "1:1 公司信息"
merchants ||--o{ merchant_knowledge_chunks : "1:N 公司知识(RLS)"
merchants ||--o{ articles : "1:N 文章(RLS)"
merchants ||--o{ tasks : "1:N 生成任务(RLS)"
merchants ||--o{ chat_conversations : "1:N 会话(RLS)"
chat_conversations ||--o{ chat_messages : "1:N 消息(RLS)"
merchants ||--o{ chat_memory_docs : "1:N AI记忆(RLS)"
merchants ||--o{ cover_projects : "1:N 封面项目(RLS)"
platform_rules : "全局共享(无RLS) 规则/限流词/违禁词"
llm_function_configs : "全局共享(无RLS) 功能级LLM配置"
cover_ai_configs : "全局共享(无RLS) 封面AI配置"
global_knowledge_docs : "全局共享(无RLS) 聊天全局知识"管理端对表的访问方式:全部通过 AdminDb(无 RLS)跨租户读写;platform_rules/llm_function_configs/cover_ai_configs/global_knowledge_docs 本身无 RLS。
8. 关键业务流程
8.1 管理员登录
- 浏览器访问
https://admin.jvguang.com→ Nginx 443 → 中间件校验内网 IP。 - 前端
Login.tsx提交账号密码 →POST /api/admin/login。 - 后端
secrets.compare_digest校验(写死账号来自.env:ADMIN_USERNAME/ADMIN_PASSWORD)→ 签发role=admin的 access token(TTL 由access_token_ttl_hours控制)。 - 前端按「记住我」偏好存 token → 跳转
/dashboard;后续请求自动携带Bearer。
8.2 模型配置热切换(全局影响最大)
ModelConfig.tsx修改某个 function_key 的 provider/model/api_key →PUT /api/admin/llm/function-configs/{key}。admin_service.update_llm_function_config:校验 + Fernet 加密 api_key 落库 →_refresh_cache_entry更新内存缓存 →llm_client.reload()。LLMClientProxy按provider:model:api_key:base_urlsignature 自动失效旧 provider、重建新 provider(HTTP 连接池同步切换)。- 影响面:小程序/Web 端所有走
chat_for_function/chat_json_for_function的 AI 功能(文章生成、合规、标题、封面、聊天)。
8.3 人工客服接管
ChatSessions.tsx列表(merchants LEFT JOIN chat_conversations)→ 选择商家 → 查看消息(游标分页)。- 关闭「AI 自动回复」→
chat_ws.set_auto_reply_enabled(false)→ 商家新消息不再触发 AI。 - 点击「AI 起草」→
POST .../ai-draft→chat_ai.generate_admin_reply_draft(临时事务内注入该商家 RLS 上下文读取上下文,不落库)。 - 编辑后发送 →
chat_ws.send_admin_message_to_merchant→ 落库(sender_role=admin)+ 经notify_merchantWS 推送商家端。
9. 部署与运维
9.1 构建
cd admin
npm install
npm run build # tsc && vite build → 产物 dist/产物部署到服务器 admin/dist(Nginx root /opt/xhs-saas/admin/dist,location /admin/)。
9.2 Nginx(backend/deploy/nginx-admin-intranet.conf)
admin.jvguang.com:/admin/静态托管 +/api/admin/与/api/反代127.0.0.1:8000+/api/cover/uploads/、/health。api.jvguang.com:/api/chat/ws需配置Upgrade/Connection头支持 WebSocket;其余/api/*反代。- 建议在 Nginx 层再叠加
allow/denyIP 白名单(双重保险)。
9.3 关键环境变量(backend/.env)
| 变量 | 说明 |
|---|---|
ADMIN_USERNAME / ADMIN_PASSWORD | 后台登录账号密码(生产要求 ≥12 位) |
ADMIN_INTRANET_ONLY | true 时仅内网可访问 |
ADMIN_ALLOWED_CIDRS | 放行网段(默认内网三大段 + 127) |
ADMIN_TRUSTED_PROXIES | 可信代理 IP(填 Nginx 内网 IP 才信任 X-Forwarded-For) |
LLM_CONFIG_ENC_KEY | Fernet 加密密钥(生产必填,validate_runtime_security 校验) |
CORS_ORIGINS | 需包含 https://admin.jvguang.com |
注意:
.env修改后需重启后端(uvicorn)才生效。
10. 影响分析汇总
| 变更点 | 影响范围 | 风险级别 |
|---|---|---|
| 修改 LLM 功能级配置 / 封面 AI 配置 | 全平台(小程序+Web 所有 AI 功能) | 高 |
| 平台规范(Rules)增删改 / 重建向量 | 所有商家的文章生成合规召回 | 中 |
| 全局知识库增删改 | 所有商家聊天 AI 回答与引导问题 | 中 |
| 删除商家 | 级联删除该商家全部数据(文章/任务/图片/会话/记忆/封面项目) | 高 |
| 删除某商家记忆文档 | 该商家 AI 遗忘历史偏好 | 低 |
| 关闭某商家 AI 自动回复 | 该商家聊天由人工接管 | 低 |
修改 admin_intranet 相关配置 | 后台可达性(改错可能锁死后台或暴露公网) | 高 |
修改 deps.py::AdminDb / RLS 策略 | 数据隔离边界,错误配置可能造成跨租户数据泄露 | 高 |
11. 常见问题
- 公网访问后台返回 403:
ADMIN_INTRANET_ONLY=true+ 当前网络出口 IP 不在白名单。需将 WiFi 公网出口 IP 加入ADMIN_ALLOWED_CIDRS;路由器重启后 IP 变化需重新配置。 - 模型配置保存后不生效:检查是否命中内存缓存(
LLMClientProxy按 signature 失效);修改后确认llm_client.reload()被调用;后端日志可见LLM provider=... model=...重建信息。 - 封面神器生成失败排查:使用
ModelConfig的诊断面板(/api/admin/cover-ai/diagnose)查看jimeng_credential_source、selected_service、jimeng_has_access_key/secret_key等。 - 聊天会话列表缺少商家:列表以 merchants 为主表 LEFT JOIN,理论上所有商家都应出现;若缺失说明 merchants 表数据异常或搜索条件过严。