# GEO 双后台与后端技术架构方案 V1 > 工作记录说明:本文仍保留作为历史架构记录。其中涉及浏览器插件执行链路、`/api/callback/plugin/*`、`plugin_sessions`、`installation_token` 的相关章节,自 2026-04-20 起视为旧版设计;当前实现请以 desktop client 方案和最新代码为准。 ## 1. 文档信息 | 项目 | 内容 | | --- | --- | | 文档名称 | GEO 双后台与后端技术架构方案 V1 | | 文档版本 | V1.0 | | 文档状态 | 待评审 | | 创建日期 | 2026-03-25 | | 适用范围 | `admin-web`、`ops-admin-web` 与 Go 后端整体架构设计 | | 关联文档 | `docs/geo-platform-prd-v1.md` | | 关联文档 | `docs/geo-platform-ops-admin-prd-v1.md` | | 关联文档 | `docs/geo-platform-tech-architecture-v1-50k.md` | ## 2. 目标与结论 ### 2.1 建设目标 本方案用于明确 GEO 平台在 V1 阶段的双后台形态与后端落地方式,满足以下目标: - 面向租户提供独立的业务后台 `admin-web` - 面向平台内部提供独立的管理后台 `ops-admin-web` - 后端统一采用 Go 实现,控制复杂度,同时保留后续拆分能力 - 支撑内容生成、知识学习、任务运维、额度管理、平台配置和审计能力 - 在 V1 阶段做到“结构清晰、实现收敛、可持续演进” ### 2.2 核心结论 V1 推荐采用以下架构策略: - 前端采用 `pnpm workspace + Vue 3 + TypeScript + ant-design-vue + Vite 8(截至 2026-03 官方稳定主线)` - 前端拆分为两个独立应用:`apps/admin-web` 和 `apps/ops-admin-web` - 公共能力通过 `packages/*` 复用,而不是让两个应用互相引用业务代码 - 后端采用 `Go + Gin + PostgreSQL + Redis + RabbitMQ + Qdrant + 对象存储` - 对象存储支持双实现:公有云部署推荐 `阿里云 OSS + CDN`,私有化部署推荐 `MinIO + Nginx / CDN` - 工程脚手架可使用 [`sponge`](https://github.com/go-dev-frame/sponge),但仅用于项目初始化、基础设施接线与简单样板生成;不直接生成业务 `handler/service/dao` 主体代码,领域边界仍以本文的 `transport -> app -> domain -> repository` 分层为准 - 后端拆分为 `gateway + tenant-api + platform-api + scheduler + 多个 Worker`,其中 `gateway` 必须保持超薄 - API 按路由前缀隔离:`/api/tenant/*` 与 `/api/platform/*` - 权限按两层建模:`tenant_role` 与 `platform_role` - 重任务统一异步化,任务进度通过 `SSE` 或短轮询回写 ### 2.3 架构边界 | 维度 | `admin-web` | `ops-admin-web` | | --- | --- | --- | | 服务对象 | 租户用户 | 平台内部人员 | | 数据范围 | 当前租户 | 全平台或指定租户 | | 核心目标 | 生成、发布、查看内容与数据 | 管租户、管配置、管任务、管风险 | | 权限模型 | `tenant_role` | `platform_role` | | API 前缀 | `/api/tenant/*` | `/api/platform/*` | ## 3. 仓库结构方案 ### 3.1 推荐目录 ```text D:\project\geo ├─ apps │ ├─ admin-web │ ├─ ops-admin-web │ └─ browser-extension ├─ packages │ ├─ ui │ ├─ shared-types │ ├─ http-client │ ├─ utils │ ├─ eslint-config │ └─ tsconfig ├─ server │ ├─ cmd │ │ ├─ gateway │ │ ├─ tenant-api │ │ ├─ platform-api │ │ ├─ scheduler │ │ ├─ worker-generate │ │ ├─ worker-knowledge │ │ ├─ worker-analytics │ │ └─ worker-publish-callback │ ├─ internal │ ├─ migrations │ ├─ sql │ └─ pkg ├─ deploy │ ├─ docker-compose │ └─ k8s └─ docs ``` ### 3.2 前端共享包建议 - `packages/ui` - 通用布局、表格筛选栏、状态标签、详情抽屉、权限按钮 - `packages/shared-types` - 前后端共用 DTO、分页结构、状态枚举、角色枚举 - `packages/http-client` - Axios 实例、鉴权拦截器、错误处理、统一响应解包 - `packages/utils` - 时间、金额、脱敏、下载、表格导出等工具 - `packages/eslint-config` - 统一 ESLint 规则 - `packages/tsconfig` - 统一 TS 配置基线 ### 3.3 是否需要第三个前端应用 当前双后台方案覆盖了租户侧和平台侧的控制面,但租户侧 V1 的媒体绑定与手动发布还依赖独立执行面。 因此 V1 建议同步建设: - `apps/browser-extension` 该应用不属于当前“双后台”主体,但属于 V1 必选执行端,负责真实登录检测、绑定回传、图片上传、手动发布和状态校验。 ## 4. 前端完整方案 ## 4.1 `apps/admin-web` 定位 租户端后台,主要服务于租户管理员与编辑,负责: - 工作台 - 文章生成与管理 - 品牌与知识库管理 - 媒体账号绑定与手动发布 - 数据追踪与套餐额度查看 ### 4.1.1 路由建议 ```text /login /workspace /articles /articles/:id /brands /knowledge /media /tracking /account ``` ### 4.1.2 页面特点 - 业务操作多 - 任务状态多 - 详情页和表单较多 - 需要关注生成与发布的过程反馈 ## 4.2 `apps/ops-admin-web` 定位 平台管理员端,主要服务于超级管理员、平台运营、客服支持、财务运营、审核风控与技术运维,负责: - 平台工作台 - 租户中心 - 套餐与额度 - 平台用户与角色 - 模型中心 - 内容配置 - 任务运维 - 监控告警 - 审计中心 ### 4.2.1 路由建议 ```text /login /platform/dashboard /platform/tenants /platform/tenants/:id /platform/plans /platform/platform-users /platform/models /platform/content /platform/tasks /platform/monitoring /platform/audit ``` ### 4.2.2 页面特点 - 列表、筛选、统计卡片较多 - 高风险操作较多 - 权限粒度更细 - 更偏运维、审计、治理和配置管理 ## 4.3 前端技术栈建议 - `vue` - `typescript` - `vite` - `pnpm` - `ant-design-vue` - `vue-router` - `pinia` - `@tanstack/vue-query` - `axios` - `zod` - `@vueuse/core` - `dayjs` - `vitest` ## 4.4 前端工程规范 - 每个应用独立 `src`,共享能力全部进入 `packages` - 菜单、按钮、路由权限全部由权限配置表驱动 - 页面模式统一为:`筛选区 + 表格区 + 详情抽屉 / 详情页` - 长任务状态统一使用 `状态标签 + 默认轮询`,仅在存在运行中任务的活跃页面临时升级为 `SSE` - 高风险按钮统一带确认弹窗和原因输入框 ## 4.5 前端部署建议 - `admin-web` 和 `ops-admin-web` 独立构建、独立发布 - 推荐独立域名或子路径: - `admin.xxx.com` - `ops.xxx.com` - 两套前端都走 CDN,后端统一走 API 域名 ## 5. 后端完整方案 ## 5.1 V1 后端总体策略 V1 推荐: - `1 个统一网关出口` - `2 个 Go API 服务` - `1 个 Scheduler` - `4 类异步 Worker` - `1 个浏览器插件执行端` - `1 套统一基础设施` 其中: - `tenant-api` 负责租户侧核心业务 - `platform-api` 负责平台治理与内部管理 - `gateway` 负责统一接入、路由转发、公共鉴权、租户级限流与 `request_id` 注入 V1 保留 `gateway`,但必须满足以下硬约束: - 只做 `route + auth + rate limit + request_id/trace_id 注入 + 错误响应封装` - 不承载任何 `tenant/*` 或 `platform/*` 业务逻辑 - 不直接写 PostgreSQL 业务表,不发 MQ 业务消息,不做任务编排 - 若未来部署环境极简,可由 `Ingress / Nginx` 直接分流到 `tenant-api` 与 `platform-api`;本文默认仍保留超薄 `gateway` 这样可以避免: - 过早微服务化 - 大量跨服务联调 - 权限和数据边界复杂化 - 运维成本提前爆炸 同时,V1 不建议把 `worker-generate / worker-knowledge / worker-analytics / worker-publish-callback` 合并成单一 Worker 进程,因为: - 交互式生成链路的时延目标高于知识学习和统计聚合 - LLM、Embedding、统计聚合的资源模型不同 - 回调补偿链路需要与用户生成链路故障隔离 - 运维简化更适合通过共享容器基座、统一 Helm 模板和统一日志规范实现,而不是牺牲任务隔离 ## 5.2 Go 后端目录结构 ```text server ├─ cmd │ ├─ gateway │ ├─ tenant-api │ ├─ platform-api │ ├─ scheduler │ ├─ worker-generate │ ├─ worker-knowledge │ ├─ worker-analytics │ └─ worker-publish-callback ├─ internal │ ├─ bootstrap │ ├─ shared │ │ ├─ auth │ │ ├─ config │ │ ├─ middleware │ │ ├─ observability │ │ ├─ plugin │ │ ├─ retrieval │ │ ├─ scheduler │ │ ├─ sse │ │ ├─ repository │ │ │ ├─ postgres │ │ │ ├─ redis │ │ │ ├─ rabbitmq │ │ │ ├─ qdrant │ │ │ └─ objectstorage │ │ └─ dto │ ├─ tenant │ │ ├─ transport │ │ ├─ app │ │ ├─ domain │ │ └─ repository │ ├─ platform │ │ ├─ transport │ │ ├─ app │ │ ├─ domain │ │ └─ repository │ ├─ jobs │ └─ gateway ├─ migrations ├─ sql └─ pkg ``` ## 5.3 API 路由分层建议 ### 5.3.1 公共接口 - `/api/health/*` - `/api/auth/*` ### 5.3.2 租户端接口 - `/api/tenant/workspace/*` - `/api/tenant/articles/*` - `/api/tenant/brands/*` - `/api/tenant/knowledge/*` - `/api/tenant/media/*` - `/api/tenant/tracking/*` - `/api/tenant/account/*` ### 5.3.3 平台管理员端接口 - `/api/platform/dashboard/*` - `/api/platform/tenants/*` - `/api/platform/plans/*` - `/api/platform/platform-users/*` - `/api/platform/models/*` - `/api/platform/content/*` - `/api/platform/integrations/*` - `/api/platform/tasks/*` - `/api/platform/monitoring/*` - `/api/platform/audit/*` ### 5.3.4 回调与内部接口 - `/api/callback/plugin/*` - `/api/internal/metrics/*` - `/api/internal/task-events/*` ### 5.3.5 网关转发关系 - `/api/auth/*` -> `gateway` 或共享认证模块 - `/api/tenant/*` -> `tenant-api` - `/api/platform/*` -> `platform-api` - `/api/callback/*` -> `tenant-api` ## 5.4 后端二进制职责 | 二进制 | 作用 | | --- | --- | | `cmd/gateway` | 统一 API 出口、无状态路由分发、基础鉴权、租户级限流、`request_id/trace_id` 注入与统一错误响应封装 | | `cmd/tenant-api` | 提供租户端业务接口、任务状态接口、按需 SSE、插件会话与插件回调接口 | | `cmd/platform-api` | 提供平台管理员端接口、租户治理、模型配置、审计与监控查询 | | `cmd/scheduler` | 扫描定时生成、数据监控等到期任务,生成调度批次并入队 | | `cmd/worker-generate` | 处理模板生成、Prompt 生成、批量生成与文章优化任务,并负责 RAG 检索、LLM 超时/限流/并发池控制 | | `cmd/worker-knowledge` | 处理知识学习、解析、批量 Embedding、Qdrant 写入与 chunk 元数据维护 | | `cmd/worker-analytics` | 处理问题采集、分析快照、统计聚合、缓存刷新;默认走低优先级模型通道 | | `cmd/worker-publish-callback` | 处理发布回调、状态回写、失败补偿 | ## 5.5 后端模块职责 ### 5.5.1 `shared/auth` - 登录 - Token 颁发与校验 - 用户身份识别 - 平台角色 / 租户角色装载 ### 5.5.2 `shared/retrieval` - 统一封装 query rewrite、filter 构造、Qdrant 检索、rerank 与上下文拼装 - 为 `worker-generate` 暴露品牌知识 RAG 检索入口 - V1 将 `retrieval_logs` 和 badcase 采样先写文件日志或对象存储,后续再升级为数据库评测体系 ### 5.5.3 `tenant` - 租户基础资料 - 租户状态 - 租户成员与租户角色 ### 5.5.4 `platform` - 平台管理员用户 - 平台角色 - 平台配置与平台级查询 ### 5.5.5 `tenant/article` / `tenant/brand` / `tenant/knowledge` - 租户业务核心能力 - 生成内容、品牌资料、知识库管理 ### 5.5.6 `platform/quota` / `platform/plan` - 套餐配置 - 配额消耗 - 配额补量 - 到期与重置规则 ### 5.5.7 `platform/model` - LLM 配置 - Embedding 配置 - 限流策略 - 默认模型策略 ### 5.5.8 `tenant/task` + `platform/task` - 任务入队 - 状态查询 - 重试与终止 - 死信处理 ### 5.5.9 `platform/monitoring` - 服务健康 - 队列状态 - Worker 状态 - 告警汇总 ### 5.5.10 `platform/audit` - 操作日志 - 配置变更日志 - 额度变更日志 - 风险操作日志 ### 5.5.11 `shared/observability` - 统一结构化日志规范与日志字段 - 统一 `request_id`、`trace_id`、`task_batch_id` 透传 - Prometheus 指标、健康检查、慢查询与队列深度观测 - 为 API、MQ、Worker 共用的错误码与告警标签提供基础设施 ## 5.6 服务边界建议 ### 5.6.1 `tenant-api` 负责 - 租户工作台 - 品牌、文章、知识库 - 媒体绑定与发布记录 - 生成任务提交与状态查询 - 租户侧额度消耗校验 - 发布回调接收 ### 5.6.2 `platform-api` 负责 - 平台工作台 - 租户管理 - 套餐与额度策略 - 平台用户与平台角色 - 模型配置与模板规则 - 任务运维查询与重试控制 - 监控告警与审计中心 ### 5.6.3 两服务协作原则 - `platform-api` 不直接承载租户高频业务流量 - `tenant-api` 不同步依赖 `platform-api` 完成核心链路 - 平台侧对租户业务的控制,优先通过数据库规则、缓存配置或内部命令完成 - 需要重试或控制任务时,由 `platform-api` 写控制记录并重新入队或调用内部接口 ## 6. 认证与权限架构 ## 6.1 统一身份模型 建议统一 `users` 主表,但角色绑定拆分: - `platform_user_roles` - `tenant_memberships` 这样一个账号可以: - 既是平台内部用户 - 也可能是某个租户的成员 但两种权限链路必须分开校验。 ## 6.2 权限模型 ### 6.2.1 平台角色 `platform_role` - `super_admin` - `ops` - `sre` ### 6.2.2 租户角色 `tenant_role` - `tenant_admin` - `editor` ### 6.2.3 租户角色能力边界 | 角色 | 主要能力 | 明确限制 | | --- | --- | --- | | `tenant_admin` | 租户设置、成员管理、模板/Prompt/品牌/知识/媒体、发布、配额查看、风险操作确认 | 无平台级治理权限 | | `editor` | 创建与编辑文章、模板、Prompt、品牌、知识、媒体发布、查看追踪数据 | 不能管理成员、套餐策略、平台级配置 | V1 权限模型按当前产品裁剪口径收敛为 `tenant_admin + editor` 两种租户角色;`viewer` 暂不单列,若后续出现严格只读协作者场景,可再由 `editor` 细分。 ### 6.2.4 Prompt 分享身份 `kol_profile` - `kol` 不是权限角色,而是用户在 Prompt 分享场景下的作者/达人身份 - `kol` 用户可生成分享码,供普通用户导入新的“文章模板类型” - 分享内容本质上是“模板卡片 + 变量槽位定义 + 使用说明 + 受保护 Prompt 资产引用”的快照,而不是裸 Prompt 文本 - 导入后会在工作台或模板页形成新的模板卡片,作为平台预设模板之外的扩展文章类型 - 公司名、地址、品牌名、联系方式等租户专属字段仍由导入方在变量槽位中自行填写或绑定 - KOL 的原始 Prompt 正文对普通用户不可见,不可导出,不可在前端编辑,用于保护 Prompt 版权 - `kol_profile` 通过 `prompt_share_profiles` 与 `prompt_share_codes` 建模,不参与 RBAC 鉴权 ## 6.3 鉴权中间件顺序 1. Token 校验 2. 用户身份解析 3. 路由前缀识别 4. 平台角色或租户角色装载 5. 资源范围校验 6. 风险操作校验 7. 审计上下文注入 ## 6.4 风险操作要求 以下操作建议统一纳入风险操作: - 冻结 / 解冻租户 - 调整套餐额度 - 修改模型默认策略 - 修改敏感词规则 - 批量重试任务 - 修改平台适配器配置 这些操作至少具备: - 二次确认 - 操作原因 - 审计日志 ## 7. 数据与中间件方案 ## 7.1 PostgreSQL 负责: - 用户、租户、成员、角色关系 - 品牌、文章、发布记录 - 套餐、额度、账期 - 模型配置、模板配置 - 任务记录 - 告警记录 - 审计日志 - 配额预扣与调度租约 - 知识 chunk 元数据 ## 7.2 Redis 负责: - 登录黑名单 - 高频查询缓存 - 仪表盘热点数据 - 任务短期状态缓存 - 限流计数 - SSE 跨 Pod 广播 ## 7.3 RabbitMQ 负责: - 文章生成任务 - 知识学习任务 - 分析聚合任务 - 发布回调任务 - 死信队列 ## 7.4 Qdrant 负责: - 知识库向量存储 - RAG 检索 ## 7.5 对象存储 负责: - 原始文档 - 图片素材 - 导入导出文件 - 原始抓取结果 - 原始模型回答与插件回调归档 ## 8. 双后台与后端交互图 以下为主架构的宏观交互图,细化后的闭环版本以 §13.5.1 为准。 ```mermaid flowchart LR subgraph FE["前端应用"] AW["admin-web
租户端"] OW["ops-admin-web
平台管理员端"] EXT["browser-extension
V1 发布执行端"] end AW --> CDN["CDN / Nginx"] OW --> CDN CDN --> ING["Ingress / API Gateway"] EXT --> ING ING --> GW["gateway"] GW --> TA["tenant-api"] GW --> PA["platform-api"] SCH["scheduler"] --> PG["PostgreSQL"] SCH --> MQ["RabbitMQ"] TA --> PG["PostgreSQL"] TA --> REDIS["Redis"] TA --> MQ["RabbitMQ"] TA --> OBJ["Object Storage"] TA --> QD["Qdrant"] PA --> PG PA --> REDIS PA --> MQ MQ --> WG["worker-generate"] MQ --> WK["worker-knowledge"] MQ --> WA["worker-analytics"] MQ --> WP["worker-publish-callback"] WG --> PG WG --> REDIS WG --> QD WK --> PG WK --> QD WK --> OBJ WA --> PG WA --> REDIS WA --> OBJ WP --> PG WP --> REDIS PA --> TA ``` ## 9. 后端结构图 以下为主架构的模块示意图;二进制职责、共享模块和运行约束以 §13.5 与 §13.13 为准。 ```mermaid flowchart TB subgraph CMD["cmd"] GWBIN["gateway"] TENBIN["tenant-api"] PLTBIN["platform-api"] SCHBIN["scheduler"] GENBIN["worker-generate"] KBBIN["worker-knowledge"] ANABIN["worker-analytics"] PUBBIN["worker-publish-callback"] end subgraph SHARED["internal/shared"] SAUTH["auth"] SMIDDLE["middleware"] SPLUGIN["plugin"] SRET["retrieval"] SSCHED["scheduler"] SREPO["shared repositories"] SSSE["sse"] SOBS["observability"] end subgraph TENANT["internal/tenant"] TTRANS["transport"] TAPP["app"] TDOMAIN["domain"] TREPO["repository"] end subgraph PLATFORM["internal/platform"] PTRANS["transport"] PAPP["app"] PDOMAIN["domain"] PREPO["repository"] end subgraph JOBS["internal/jobs"] JGEN["generate job"] JKB["knowledge job"] JANA["analytics job"] JPUB["publish callback job"] end subgraph INFRA["infra"] PGREPO["postgres"] REDISREPO["redis"] MQREPO["rabbitmq"] QDREPO["qdrant"] OBJREPO["objectstorage"] end GWBIN --> SAUTH GWBIN --> SMIDDLE TENBIN --> TTRANS TENBIN --> SAUTH TENBIN --> SPLUGIN TENBIN --> SSSE TENBIN --> SOBS PLTBIN --> PTRANS PLTBIN --> SAUTH PLTBIN --> SOBS SCHBIN --> SSCHED SCHBIN --> SOBS TTRANS --> TAPP TAPP --> TDOMAIN TAPP --> TREPO PTRANS --> PAPP PAPP --> PDOMAIN PAPP --> PREPO GENBIN --> JGEN KBBIN --> JKB ANABIN --> JANA PUBBIN --> JPUB JGEN --> SRET JGEN --> TREPO JKB --> TREPO JANA --> PREPO JPUB --> TREPO JPUB --> PREPO TREPO --> SREPO PREPO --> SREPO SRET --> SREPO SREPO --> PGREPO SREPO --> REDISREPO SREPO --> MQREPO SREPO --> QDREPO SREPO --> OBJREPO ``` ## 10. 核心链路设计 ## 10.1 租户端生成链路 1. `admin-web` 提交生成请求 2. API 校验租户身份、额度、参数 3. `tenant-api` 在同一 PostgreSQL 事务内完成“额度预扣 / 保留 + `generation_tasks` / `task_records` 创建 + 文章占位记录初始化” 4. 事务提交后写入 RabbitMQ 5. `worker-generate` 消费任务,先经 `shared/retrieval` 执行 `query rewrite -> filter -> Qdrant 检索 -> rerank -> 上下文拼装` 6. `worker-generate` 在超时、限流、并发池保护下调用模型 7. 成功时在同一 PostgreSQL 事务内写入 `article_versions`、更新 `articles`、确认额度消耗;失败时写失败状态并按条退还额度 8. 结果写入 Redis,前端通过 SSE 或轮询感知任务进度 ## 10.2 平台端额度调整链路 1. `ops-admin-web` 发起额度变更 2. API 校验 `platform_role` 3. 写入额度变更记录 4. 更新租户额度表与缓存 5. 写入审计日志 6. 租户端下一次请求按新额度生效 ## 10.3 平台端任务排查链路 1. `ops-admin-web` 查询失败任务列表 2. API 聚合 PostgreSQL 任务信息、错误信息与重试信息 3. 平台人员发起重试 4. API 写入重试记录并重新入队 5. Worker 执行后回写结果 6. 审计中心记录操作人和结果 ## 10.4 监控与告警链路 1. Go API 与 Worker 暴露指标 2. 监控系统采集服务、队列、缓存、数据库指标 3. 告警服务生成异常记录 4. `ops-admin-web` 查询并展示告警状态 ## 11. 部署建议 ## 11.1 本地开发 - 前端:`pnpm` 工作区本地联调 - 基础设施:`docker compose` 仅启动 PostgreSQL、Redis、RabbitMQ、Qdrant、MinIO - 后端服务建议本地 `go run`,按需启动: - `go run ./server/cmd/gateway` - `go run ./server/cmd/tenant-api` - `go run ./server/cmd/platform-api` - `go run ./server/cmd/scheduler` - `go run ./server/cmd/worker-generate` - `go run ./server/cmd/worker-knowledge` - `go run ./server/cmd/worker-analytics` - `go run ./server/cmd/worker-publish-callback` - 建议提供 `make dev-init` 或等价任务脚本,统一完成: - 执行 migration - 创建 RabbitMQ 队列 / exchange / routing key - 初始化 MinIO bucket - 写入最小种子数据与本地模型通道配置 ## 11.2 测试与预发 - 前端独立构建产物 - API 与 Worker 独立容器 - 使用共享测试基础设施或云托管实例 ## 11.3 线上生产 - `admin-web` 与 `ops-admin-web` 独立发布到 CDN - API 与 Worker 部署到 Kubernetes - PostgreSQL、Redis、RabbitMQ、Qdrant 使用高可用或托管方案 ## 12. 演进路线 ### 12.1 V1 - 两个前端应用 - 一个浏览器插件执行端 - 一个统一网关出口 - 两个 Go API 服务 - 一个 Scheduler - 四类 Worker - 平台端与租户端路由隔离 ### 12.2 V1.5 - 抽离统一审计模块 - 抽离模型网关模块 - 增加平台接入配置中心 ### 12.3 V2 - 按压力拆分平台 API 与租户 API - 单独拆出 `ops-bff` 或 `platform-api` - 单独拆出 `analytics-service` ## 13. V1 闭环补齐方案 ### 13.1 适用说明 本节结合以下材料对前文进行补齐修订,并作为 V1 详细落地的统一口径: - `docs/refer/*` - `docs/geo-platform-prd-v1.md` - `docs/geo-platform-ops-admin-prd-v1.md` - `docs/media-binding-and-publish-v1.md` - `docs/question-driven-monitoring-design-v1.md` - `docs/Claude_architecture_review.md` 若本节与前文较早的抽象表述存在冲突,以本节为准。 ### 13.2 修订结论 为保证 `docs/refer` 中 8 个页面在 V1 阶段形成“页面 -> 路由 -> API -> 对象 -> 任务 -> 存储 -> 状态回传”的完整闭环,V1 对总体架构做如下修订: - `apps/browser-extension` 从“后续可选”提升为 `V1 必选执行端` - 后端实际形态明确为:`gateway + tenant-api + platform-api + scheduler + 4 类 Worker + browser-extension` - `tenant-api` 按业务拆分为 `workspace / template / prompt-rule / schedule / article / optimization / brand / knowledge / media / tracking / account` - `worker-generate` 同时承载 `模板生成 / Prompt 生成 / 批量生成 / 文章优化` - 工作台模板卡片支持“平台预设 + 租户自建 + KOL 分享码导入”三种来源,导入后统一物化为租户模板 - `数据追踪` 采用“问题驱动监控”模型,最小采集单元为 `question_version x model x run_time` - 工作台、数据追踪、任务状态统一提供聚合接口,避免前端首屏发起过多散请求 - 所有长任务统一接入 `task_records + SSE + 轮询兜底` ### 13.3 功能闭环矩阵 | 功能页 | 核心路由 | 核心 API 组 | 核心对象 | 异步/执行组件 | | --- | --- | --- | --- | --- | | 工作台 | `/workspace` | `/api/tenant/workspace/*` | `articles` `article_templates` `brands` `platform_accounts` `tenant_plan_subscriptions` | `worker-generate` `worker-publish-callback` | | 模板创作 | `/articles/template` | `/api/tenant/templates/*` `/api/tenant/prompt-shares/*` `/api/tenant/articles/*` | `article_templates` `prompt_share_codes` `articles` `generation_tasks` | `worker-generate` | | 自定义生成 | `/articles/custom/*` | `/api/tenant/prompt-rules/*` `/api/tenant/schedules/*` `/api/tenant/articles/*` | `prompt_rules` `schedule_tasks` `generation_tasks` | `scheduler` `worker-generate` | | 文章优化 | `/articles/optimize` | `/api/tenant/optimizations/*` `/api/tenant/articles/*` | `optimization_tasks` `article_versions` | `worker-generate` | | 媒体管理 | `/media` | `/api/tenant/media/*` `/api/callback/plugin/*` | `media_platforms` `platform_accounts` `plugin_sessions` `publish_records` | `browser-extension` `worker-publish-callback` | | 品牌词库 | `/brands` `/brands/:id` | `/api/tenant/brands/*` | `brands` `brand_keywords` `brand_questions` `brand_question_versions` `competitors` | `worker-analytics` | | 知识库 | `/knowledge` | `/api/tenant/knowledge/*` | `knowledge_groups` `knowledge_items` `knowledge_parse_tasks` | `worker-knowledge` | | 数据追踪 | `/tracking/overview` `/tracking/detail` | `/api/tenant/tracking/*` | `question_monitor_runs` `question_monitor_parse_results` `keyword_model_daily_metrics` `keyword_model_top_questions_daily` `keyword_model_citation_rank_daily` | `scheduler` `worker-analytics` | ### 13.4 细化前端路由 #### 13.4.1 `admin-web` ```text /login /workspace /articles/template /articles/template/create /articles/custom /articles/custom/instant /articles/custom/scheduled /articles/custom/prompts /articles/optimize /articles/:id /articles/:id/publish-records /brands /brands/:id /knowledge /media /tracking/overview /tracking/detail /account ``` #### 13.4.2 `ops-admin-web` ```text /login /platform/dashboard /platform/tenants /platform/tenants/:id /platform/plans /platform/platform-users /platform/platform-roles /platform/models/llm /platform/models/embedding /platform/models/channels /platform/models/limits /platform/content/templates /platform/content/prompts /platform/content/tags /platform/content/sensitive-rules /platform/integrations/media-platforms /platform/integrations/adapters /platform/integrations/publish-policies /platform/tasks/generation /platform/tasks/knowledge /platform/tasks/publish /platform/tasks/analytics /platform/tasks/dead-letter /platform/monitoring/services /platform/monitoring/queues /platform/monitoring/workers /platform/monitoring/storage /platform/monitoring/alerts /platform/audit/operations /platform/audit/config-changes /platform/audit/quota-changes /platform/audit/risk-actions ``` ### 13.5 服务、二进制与模块补齐 #### 13.5.1 修订后的整体交互图 ```mermaid flowchart LR AW["admin-web"] --> CDN["CDN / Nginx"] OW["ops-admin-web"] --> CDN EXT["browser-extension"] <---> AW CDN --> GW["gateway"] GW --> TA["tenant-api"] GW --> PA["platform-api"] SCH["scheduler"] --> PG["PostgreSQL"] SCH --> MQ["RabbitMQ"] TA --> PG TA --> REDIS["Redis"] TA --> MQ TA --> OBJ["Object Storage"] TA --> QD["Qdrant"] PA --> PG PA --> REDIS PA --> MQ EXT --> CB["/api/callback/plugin/*"] CB --> TA MQ --> WG["worker-generate"] MQ --> WK["worker-knowledge"] MQ --> WA["worker-analytics"] MQ --> WP["worker-publish-callback"] WG --> QD WA --> OBJ ``` #### 13.5.2 二进制职责补齐 | 二进制/执行端 | 职责 | | --- | --- | | `cmd/gateway` | 统一入口、公共鉴权、限流、`request_id/trace_id` 注入与统一错误响应封装;保持无状态,支持水平扩容 | | `cmd/tenant-api` | 承载租户侧全部业务接口、SSE、插件会话管理、回调落库 | | `cmd/platform-api` | 承载平台治理、套餐额度、平台用户、模型中心、平台接入、监控审计 | | `cmd/scheduler` | 扫描 `schedule_tasks` 和数据监控计划,按到期窗口生成调度批次并入队 | | `cmd/worker-generate` | 执行模板生成、Prompt 生成、批量生成、文章优化;通过 `shared/retrieval` 做 RAG 检索,并使用独立 LLM 并发池控制交互任务 | | `cmd/worker-knowledge` | 执行文档解析、URL 抓取、文本切片、批量 Embedding、Qdrant 写入、chunk 元数据维护 | | `cmd/worker-analytics` | 执行问题驱动监控、回答解析、日级聚合、排行榜刷新、缓存刷新;采集任务默认走低优先级模型通道 | | `cmd/worker-publish-callback` | 处理发布回调补偿、账号状态检测结果、失败重放与死信回写 | | `apps/browser-extension` | 真实登录检测、账号绑定、图片上传、手动发布、状态检查、本地 adapter 执行 | #### 13.5.3 租户侧模块补齐 | 模块 | 职责 | | --- | --- | | `tenant/workspace` | 工作台聚合指标、最近生成、额度摘要、模板卡片下发;卡片来源支持平台预设、租户自建与 KOL 分享导入 | | `tenant/template` | 模板定义、模板 schema、模板版本、模板生成入口、KOL 分享模板的变量定制与落库;不向导入方暴露受保护 Prompt 正文 | | `tenant/prompt-rule` | Prompt 规则 CRUD、启停、默认语气/字数配置、作者身份信息、分享码导出与导入;支持变量槽位定义与版权保护 | | `tenant/schedule` | 定时生成计划 CRUD、启停、下一次执行时间维护 | | `tenant/article` | 文章主记录、详情、预览、复制、删除、发布前读取 | | `tenant/optimization` | 优化任务、优化方向、版本保存、未完成任务入口 | | `tenant/brand` | 品牌、关键词、问题集、问题版本、竞品库 | | `tenant/knowledge` | 分组、知识条目、来源类型、学习任务状态 | | `tenant/media` | 平台清单、平台账号、插件会话、发送记录、状态检测 | | `tenant/tracking` | 数据概览、趋势图、高频问题、引用排行、品牌关键词模型筛选 | | `tenant/account` | 套餐、额度、重置时间、升级入口占位 | #### 13.5.4 平台侧模块补齐 | 模块 | 职责 | | --- | --- | | `platform/tenant` | 租户开通、冻结解冻、套餐关联、额度治理 | | `platform/plan` + `platform/quota` | 套餐档位、额度策略、补量、账期重置 | | `platform/model` | LLM、Embedding、渠道密钥、限流、默认策略 | | `platform/content` | 平台级模板、Prompt 规则、分类标签、敏感词规则 | | `platform/integration` | 媒体平台清单、平台分类、adapter 注册、发布策略 | | `platform/task` | 任务运维、批量重试、死信处理、执行历史 | | `platform/monitoring` | 服务、队列、Worker、存储、告警 | | `platform/audit` | 操作日志、配置变更、额度变更、风险操作 | ### 13.6 核心 API 补齐 #### 13.6.1 租户侧 API - `/api/tenant/workspace/overview` - `/api/tenant/workspace/recent-articles` - `/api/tenant/workspace/quota-summary` - `/api/tenant/workspace/template-cards` - `/api/tenant/templates` - `/api/tenant/templates/{id}` - `/api/tenant/templates/{id}/schema` - `/api/tenant/templates/{id}/generate` - `/api/tenant/prompt-rules` - `/api/tenant/prompt-rules/{id}` - `/api/tenant/prompt-rules/{id}/share-code` - `/api/tenant/prompt-shares/resolve/{shareCode}` - `/api/tenant/prompt-shares/import` - `/api/tenant/prompt-share-profiles/me` - `/api/tenant/schedules` - `/api/tenant/schedules/{id}` - `/api/tenant/schedules/{id}/enable` - `/api/tenant/schedules/{id}/disable` - `/api/tenant/articles` - `/api/tenant/articles/{id}` - `/api/tenant/articles/{id}/versions` - `/api/tenant/articles/{id}/publish-records` - `/api/tenant/optimizations` - `/api/tenant/optimizations/{id}` - `/api/tenant/brands` - `/api/tenant/brands/{id}` - `/api/tenant/brands/{id}/keywords` - `/api/tenant/brands/{id}/questions` - `/api/tenant/brands/{id}/competitors` - `/api/tenant/knowledge/groups` - `/api/tenant/knowledge/items` - `/api/tenant/knowledge/parse-tasks` - `/api/tenant/media/platforms` - `/api/tenant/media/platform-accounts` - `/api/tenant/media/platform-accounts/{id}/check` - `/api/tenant/media/plugin-sessions` - `/api/tenant/media/publish-records` - `/api/tenant/tracking/summary` - `/api/tenant/tracking/trend` - `/api/tenant/tracking/top-questions` - `/api/tenant/tracking/citation-rank` - `/api/tenant/account/plan` - `/api/tenant/account/quota` #### 13.6.2 平台侧 API - `/api/platform/dashboard/*` - `/api/platform/tenants/*` - `/api/platform/plans/*` - `/api/platform/platform-users/*` - `/api/platform/models/*` - `/api/platform/content/*` - `/api/platform/integrations/*` - `/api/platform/tasks/*` - `/api/platform/monitoring/*` - `/api/platform/audit/*` #### 13.6.3 插件回调与内部接口 - `/api/callback/plugin/bind` - `/api/callback/plugin/publish` - `/api/callback/plugin/check` - `/api/internal/task-events` - `/api/internal/scheduler/dispatch` #### 13.6.4 统一错误响应与错误码 所有 API 建议统一返回: ```json { "code": 40301, "message": "quota_insufficient", "detail": "生成额度不足,请升级套餐或等待额度重置", "request_id": "req_xxx" } ``` 错误码段建议如下: | 错误码段 | 含义 | | --- | --- | | `400xx` | 参数校验与请求格式错误 | | `401xx` | 认证失败、Token 失效 | | `403xx` | 权限不足、额度不足、功能未开通 | | `404xx` | 资源不存在 | | `409xx` | 状态冲突、幂等冲突、重复提交 | | `429xx` | 频率限制、队列拥塞 | | `500xx` | 内部错误 | | `503xx` | 下游依赖不可用,如 `LLM / Embedding / Qdrant / ObjectStorage` | `gateway` 与各 API 服务必须共用同一套错误码枚举和响应封装,避免前后端联调时出现多种格式。 #### 13.6.5 KOL 分享码解析边界 - `/api/tenant/prompt-shares/resolve/{shareCode}` 只返回模板卡片信息、变量槽位、使用说明、作者展示信息,不返回底层 Prompt 正文 - `/api/tenant/prompt-shares/import` 在服务端完成模板物化,前端只提交变量定制结果,不接触受保护 Prompt 资产 - `/api/tenant/templates/{id}` 对 `origin_type=kol_share` 的模板仅返回可定制字段与运行配置,不返回 `prompt_template` - 真正参与生成的受保护 Prompt 仅由 `tenant-api` / `worker-generate` 在服务端读取,前端与浏览器插件都不可见 ### 13.7 异步任务、调度与幂等设计 #### 13.7.1 队列与任务类型 | 队列 | 任务类型 | 说明 | | --- | --- | --- | | `q.generate.interactive` | `article.generate.template` `article.generate.prompt` `article.optimize` | 交互式任务,高优先级,服务工作台、模板创作、自定义生成即时任务与文章优化 | | `q.generate.batch` | `article.generate.batch_item` `article.generate.schedule_item` | 批量与定时任务,低优先级,避免堵塞交互任务 | | `q.knowledge` | `knowledge.parse.file` `knowledge.parse.url` `knowledge.parse.text` | 不同来源共用解析入口,按来源类型走不同解析器 | | `q.analytics.collect` | `analytics.collect.question` | 采集任务,低于用户直触发生成任务优先级,默认使用独立模型通道或更小并发池 | | `q.analytics.aggregate` | `analytics.aggregate.daily` `analytics.refresh.cache` | 聚合与缓存刷新任务,不占用 LLM 通道 | | `q.publish-callback` | `publish.persist` `platform-account.check.persist` | 插件执行结果、账号检测结果入队补偿 | | `q.dead-letter` | `dead_letter.*` | 统一兜底失败任务 | #### 13.7.2 调度器设计 - `scheduler` 每分钟扫描一次 `schedule_tasks`,条件为 `status=enabled and next_run_at <= now()` - 使用数据库行级锁或租约字段 `dispatch_lease_until + lease_owner` 防止多实例重复派发 - 每次派发生成一个 `task_batch_id`,并为批量任务拆分出多个 `generation_tasks` - 数据追踪监控计划同样由 `scheduler` 生成 `analytics.collect.question` 任务 - 计划任务创建时默认写入 `dispatch_jitter_minutes`,将大批同时到期任务平滑散布到 `5~10 分钟` 窗口内 - `scheduler` 重启后按 `task_batch_id + request_hash` 幂等追回漏派发任务,避免重复投递 - V1 不依赖 RabbitMQ Delay Queue,统一采用“数据库到期扫描 + 普通消息队列”方式,降低实现复杂度 #### 13.7.3 事务、幂等与补偿 - 任务提交路径必须在单个 PostgreSQL 事务内完成“额度预扣 / 保留 + 任务创建 + 任务记录写入” - Worker 成功路径必须在单个 PostgreSQL 事务内完成“结果写入 + 主记录状态更新 + 额度确认” - Worker 失败路径必须在单个 PostgreSQL 事务内完成“失败状态更新 + 额度退还 / 释放” - 批量生成采用“提交时按批次预扣 + 单条失败退款 + 定期对账”模式,批次维度以 `task_batch_id` 管理 - 生成任务按 `tenant_id + source_type + request_hash + schedule_slot` 做幂等 - 插件回调按 `plugin_session_id + callback_stage` 做幂等 - `publish_records` 保留请求与响应摘要,支持补偿重放 - Worker 默认重试 3 次,超过阈值进入死信;平台端允许人工批量重试 ### 13.8 浏览器插件执行面闭环 #### 13.8.1 插件会话模型 为避免“页面一关结果丢失”,V1 引入 `plugin_sessions`: 1. 前端先调用 `/api/tenant/media/plugin-sessions` 创建一次性会话 2. 后端返回 `plugin_session_id + session_token + expire_at` 3. 前端将会话信息交给 `browser-extension` 4. 插件执行绑定、检测或发布动作 5. 插件将结果: - 回传给前端用于即时交互 - 同时回调 `/api/callback/plugin/*` 用于可靠落库 6. `tenant-api` 校验 `session_token` 后写入 `platform_accounts` 或 `publish_records` 7. 系统通过 SSE 广播结果,列表页和详情页实时刷新 #### 13.8.2 绑定/发布状态流转 - 平台账号状态:`pending -> active -> invalid/expired` - 发布状态:`unpublished -> publishing -> success/failed/pending_review` - 回调接口不直接信任浏览器 Cookie,只信任后端签发的短期 `session_token` #### 13.8.3 安全约束 - 服务端不保存第三方平台 Cookie 与登录态 - 插件仅允许注入受信后台域名 - 所有 `postMessage` / `runtime.sendMessage` 必须校验来源域名与会话 token - 所有绑定、重检、发布、失败补偿动作写入审计日志 #### 13.8.4 插件检测与降级 - `packages/shared-types` 维护 `MIN_BROWSER_EXTENSION_VERSION` 常量,作为前后端与插件共享的最低兼容版本 - 媒体页加载时,`admin-web` 先通过 `plugin.ping` / `postMessage` 握手检测插件是否安装、版本是否满足要求、能力清单是否齐备 - 未安装、被禁用或版本过低时,页面将“去绑定 / 重新检测 / 发布”按钮置灰,并展示安装或升级引导 - 插件回调会把 `client_version` 回传到 `plugin_sessions` 审计字段,便于排查兼容问题 - 降级场景下不走伪成功逻辑,统一保持前端只读提示,避免产生无法落库的假状态 ### 13.9 数据追踪闭环 #### 13.9.1 采集模型 数据追踪采用 `问题驱动监控`,最小采集单元为: `1 question_version x 1 model x 1 run_time = 1 条原始监控记录` 含义如下: - `品牌` 是租户下的监控主体 - `关键词` 是问题集合容器与聚合维度 - `问题版本` 保证历史口径稳定 - `模型` 是对比维度 - 页面只查日级聚合表,不直接扫描原始回答 #### 13.9.2 数据链路 1. 用户在品牌词库维护 `brand_keywords` 与 `brand_questions` 2. `scheduler` 按每日频率为启用的问题版本和目标模型派发监控任务 3. `worker-analytics` 调用模型得到原始回答,原文写入对象存储 4. 解析回答是否提及品牌、是否首位提及、是否首选推荐、是否正向提及、是否引用文章 5. 结果写入 `question_monitor_runs` 与 `question_monitor_parse_results` 6. 日级聚合刷新 `question_model_daily_metrics`、`keyword_model_daily_metrics`、`keyword_model_top_questions_daily`、`keyword_model_citation_rank_daily` 7. Redis 缓存 30 天摘要、趋势图、高频问题、引用排行 8. `/api/tenant/tracking/*` 统一从聚合表和缓存读取 #### 13.9.3 V1 控制策略 - 每个问题每天默认执行 `1 次` - 重要品牌或更高套餐可配置为 `2 次` - 同品牌、同模型、同日、相同 `question_hash` 可做采集去重 - 原始回答落对象存储,PostgreSQL 仅保存结构化解析与聚合结果 - 原始运行记录保留 `30 ~ 90 天`,解析结果保留 `90 天`,日级汇总保留 `180 天+` - `brand_question_versions` 仅在“启用 / 发布新监控口径”时生成新版本;编辑态默认做 `10 分钟` debounce,避免碎片化 ### 13.10 SSE 与轮询策略 #### 13.10.1 SSE 适用场景 以下场景在“存在运行中任务”期间可临时升级为 SSE: - 文章生成进度 - 文章优化进度 - 知识学习状态 - 平台账号检测状态 - 发布状态变更 - 配额刷新提醒 #### 13.10.2 事件类型 - `task.updated` - `article.generated` - `article.optimized` - `knowledge.updated` - `platform_account.updated` - `publish.updated` - `quota.updated` 统一负载字段建议: - `event_id` - `tenant_id` - `event_type` - `resource_type` - `resource_id` - `task_id` - `status` - `message` - `occurred_at` #### 13.10.3 连接策略 - 工作台、列表页、数据页默认使用 `10s` 轮询 - 仅当页面存在 `queued/running/publishing/checking` 状态的资源时,前端才建立 SSE 连接 - 单用户单租户默认只保留 `1` 条 SSE 连接;页面空闲 `60s` 且无运行中任务时主动关闭 - `tenant-api` 通过 Redis Pub/Sub 做跨 Pod 事件广播,不依赖 Sticky Session;任一 Pod 写事件后,所有订阅 Pod 都能向本地连接转发 - SSE heartbeat 调整为 `30s` - 客户端断线后按 `3s / 5s / 10s` 退避重连 - 若浏览器或网络环境不支持 SSE,则保持 `10s` 轮询 - 页面不直接监听 RabbitMQ,统一由 `tenant-api` 聚合并对前端推送 ### 13.11 核心数据模型与最小 Schema #### 13.11.1 身份、租户与额度 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `tenants` | `id` `name` `status` `created_at` `frozen_at` | `uk_tenant_name` | | `users` | `id` `email` `phone` `status` `created_at` | `uk_users_email` | | `tenant_memberships` | `id` `tenant_id` `user_id` `tenant_role` | `uk_tenant_user` | | `platform_user_roles` | `id` `user_id` `platform_role` | `uk_platform_user_role` | | `plans` | `id` `plan_code` `name` `quota_policy_json` `status` | `uk_plan_code` | | `tenant_plan_subscriptions` | `id` `tenant_id` `plan_id` `start_at` `end_at` `status` | `idx_tenant_plan_active` | | `tenant_quota_ledgers` | `id` `tenant_id` `quota_type` `delta` `balance_after` `reason` | `idx_tenant_quota_tenant_type_created` | | `quota_reservations` | `id` `tenant_id` `quota_type` `resource_type` `resource_id` `reserved_amount` `consumed_amount` `refunded_amount` `status` `expire_at` | `idx_quota_reservation_tenant_status` | #### 13.11.2 模板、Prompt、文章与优化 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `article_templates` | `id` `scope` `tenant_id` `origin_type` `share_code_id` `template_key` `template_name` `schema_json` `prompt_template` `prompt_visibility` `protected_prompt_asset_key` `card_config_json` `status` `version_no` | `uk_template_scope_key_version` | | `prompt_rules` | `id` `tenant_id` `name` `prompt_content` `scene` `default_tone` `default_word_count` `status` | `idx_prompt_rule_tenant_status` | | `prompt_share_profiles` | `id` `user_id` `display_name` `bio` `avatar_url` `share_enabled` `status` | `uk_prompt_share_profile_user` | | `prompt_share_codes` | `id` `tenant_id` `source_template_id` `owner_user_id` `share_code` `snapshot_json` `protected_prompt_asset_key` `status` `expire_at` | `uk_prompt_share_code` | | `schedule_tasks` | `id` `tenant_id` `prompt_rule_id` `target_platform_id` `cron_expr` `next_run_at` `dispatch_jitter_minutes` `lease_owner` `dispatch_lease_until` `last_dispatch_at` `status` | `idx_schedule_due` | | `articles` | `id` `tenant_id` `source_type` `template_id` `prompt_rule_id` `current_version_id` `generate_status` `publish_status` | `idx_article_tenant_created` | | `article_versions` | `id` `article_id` `version_no` `title` `html_content` `markdown_content` `word_count` `source_label` | `uk_article_version_no` | | `generation_tasks` | `id` `tenant_id` `article_id` `task_batch_id` `quota_reservation_id` `task_type` `request_hash` `status` `error_message` | `idx_generation_task_status_created` | | `optimization_tasks` | `id` `tenant_id` `article_id` `source_version_id` `target_version_id` `optimization_type` `status` | `idx_optimization_task_status` | 其中:`article_templates.scope=platform` 时 `tenant_id` 为空;`scope=tenant` 时 `tenant_id` 必填。 导入 KOL 分享码后,系统会把快照物化为当前租户自己的 `article_templates` 记录,并标记 `origin_type=kol_share`。 `article_templates.prompt_visibility=sealed` 时,模板的 Prompt 正文只允许服务端读取,前端接口不得返回。 `prompt_share_codes.snapshot_json` 只保存模板卡片信息、变量占位和使用说明;真正的 Prompt 正文通过 `protected_prompt_asset_key` 以受保护资产方式保存,不复制导出方租户的品牌、地址、媒体账号等私有数据。 #### 13.11.3 品牌与问题集 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `brands` | `id` `tenant_id` `name` `description` `status` | `uk_brand_tenant_name` | | `brand_keywords` | `id` `tenant_id` `brand_id` `name` `status` | `uk_brand_keyword_name` | | `brand_questions` | `id` `tenant_id` `brand_id` `keyword_id` `current_version_id` `status` | `idx_brand_questions_keyword` | | `brand_question_versions` | `id` `question_id` `question_text` `question_hash` `version_no` `is_active` | `uk_question_version_no` `idx_question_hash` | | `competitors` | `id` `tenant_id` `brand_id` `name` `website` `description` `product_lines_json` | `idx_competitor_brand` | #### 13.11.4 知识库 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `knowledge_groups` | `id` `tenant_id` `name` `parent_id` `sort_order` | `uk_knowledge_group_name` | | `knowledge_items` | `id` `tenant_id` `group_id` `source_type` `name` `storage_key` `status` `size_bytes` | `idx_knowledge_item_group_status` | | `knowledge_parse_tasks` | `id` `tenant_id` `knowledge_item_id` `source_type` `status` `error_message` | `idx_parse_task_status` | | `knowledge_chunks_meta` | `id` `tenant_id` `knowledge_item_id` `chunk_index` `token_count` `qdrant_point_id` `item_version` `status` | `idx_chunk_item_version` | V1 的 `retrieval_logs` 与 `rag_eval_cases` 先不落数据库表,统一写文件日志或对象存储采样归档,待评测体系成熟后再升级。 #### 13.11.5 媒体平台与插件执行 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `media_platforms` | `id` `platform_code` `name` `category` `adapter_key` `status` | `uk_media_platform_code` | | `platform_accounts` | `id` `tenant_id` `user_id` `platform_id` `platform_uid` `nickname` `avatar_url` `status` `last_check_at` | `uk_platform_account_identity` | | `plugin_sessions` | `id` `tenant_id` `user_id` `action_type` `platform_id` `session_token` `client_version` `expire_at` `status` | `uk_plugin_session_token` `idx_plugin_session_expire` | | `publish_records` | `id` `tenant_id` `article_id` `platform_account_id` `platform_id` `status` `external_article_id` `error_message` `request_payload_json` `response_payload_json` | `idx_publish_record_article_created` | #### 13.11.6 数据追踪 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `question_monitor_runs` | `id` `tenant_id` `brand_id` `keyword_id` `question_id` `question_version_id` `model_id` `run_date` `run_at` `task_batch_id` `status` `raw_answer_storage_key` | `idx_monitor_runs_query` | | `question_monitor_parse_results` | `id` `run_id` `mentioned_brand` `top1_mentioned` `first_recommended` `positive_mentioned` `citation_article_count` `citation_platform_count` `parser_version` | `uk_parse_result_run` | | `question_model_daily_metrics` | `tenant_id` `brand_id` `keyword_id` `question_id` `question_version_id` `model_id` `date` `ask_count` `mention_count` `top1_mention_count` `first_recommend_count` `positive_mention_count` `citation_count` | `uk_question_model_daily` | | `keyword_model_daily_metrics` | `tenant_id` `brand_id` `keyword_id` `model_id` `date` `ask_count` `mention_rate` `positive_mention_rate` | `uk_keyword_model_daily` | | `keyword_model_top_questions_daily` | `tenant_id` `brand_id` `keyword_id` `model_id` `date` `question_id` `score` | `idx_top_questions_daily` | | `keyword_model_citation_rank_daily` | `tenant_id` `brand_id` `keyword_id` `model_id` `date` `cited_article_id` `citation_count` | `idx_citation_rank_daily` | 保留策略建议与专项监控方案对齐:原始运行记录 `30 ~ 90 天`、解析结果 `90 天`、日级汇总 `180 天或更久`。 #### 13.11.7 平台任务与审计 | 表 | 关键字段 | 关键约束/索引 | | --- | --- | --- | | `task_records` | `id` `tenant_id` `task_type` `resource_type` `resource_id` `status` `retry_count` `task_batch_id` | `idx_task_record_status_type` | | `audit_logs` | `id` `operator_id` `tenant_id` `module` `action` `before_json` `after_json` `result` `created_at` | `idx_audit_module_created` | | `config_change_logs` | `id` `operator_id` `scope_type` `scope_id` `change_type` `diff_json` | `idx_config_change_scope` | | `quota_change_logs` | `id` `operator_id` `tenant_id` `quota_type` `delta` `reason` | `idx_quota_change_tenant` | | `risk_action_logs` | `id` `operator_id` `tenant_id` `risk_type` `reason` `result` | `idx_risk_action_tenant_created` | ### 13.12 闭环验收标准 以下标准满足时,可认为主技术架构已从“宏观方案”补齐为“可开发闭环方案”: - `工作台` 有独立聚合 API,不依赖前端拼装多个分散接口 - `模板创作` 有模板定义、schema、批量生成和任务状态落点 - `自定义生成` 有 Prompt 规则、定时任务、Scheduler 和幂等派发设计 - `文章优化` 有优化任务、版本表、保存结果与回看路径 - `媒体管理` 有插件执行端、插件会话、绑定回调、发布回调和状态同步 - `品牌词库` 有关键词、问题、问题版本、竞品库与追踪关联 - `知识库` 有分组、多来源解析策略、学习任务和对象存储落点 - `数据追踪` 有明确采集单元、聚合表、缓存策略和查询口径 - 所有长任务都有 `task_records`、SSE 事件和轮询兜底 - 所有高风险操作、配置变更、额度变更、发布失败补偿都有审计记录 ### 13.13 面向 5 万并发与简单运维的运行策略 #### 13.13.1 Gateway 水平扩展与负载均衡 - `gateway` 必须保持无状态,允许多实例水平扩展 - 线上入口通过 `Ingress / Nginx` 做 L7 负载均衡,前端无需感知后端实例 - Kubernetes 建议为 `gateway` 配置 HPA,核心观测指标为:`CPU`、`RPS`、`active_connections` - `gateway` 到 `tenant-api` / `platform-api` 之间通过集群内部 Service 直连,V1 不引入额外服务网格 - `gateway` 只允许承担统一入口职责,不允许沉淀业务编排、任务控制、数据聚合与数据库业务写入 #### 13.13.2 Scheduler 故障恢复策略 - V1 默认采用 `单活 scheduler + 健康检查 + 自动重启` - `scheduler` 重启后必须重新扫描 `next_run_at <= now()` 的计划任务,并按幂等键自动追回漏派发任务 - 若计划任务已超出允许追赶窗口,则记录为 `skipped/expired` 并写入审计日志 - 派发状态需保留 `lease_owner`、`dispatch_lease_until`、`last_dispatch_at`,便于故障排查和追赶 #### 13.13.3 PostgreSQL 分区、索引与归档 - `audit_logs`、`config_change_logs`、`quota_change_logs`、`risk_action_logs` 按月分区 - `question_monitor_runs`、`question_monitor_parse_results`、`question_model_*`、`keyword_model_*` 按日期分区 - `articles` 至少提供 `(tenant_id, created_at desc)`、`(tenant_id, generate_status, publish_status, created_at desc)` 复合索引 - 原始回答正文保留在对象存储 `30~90 天`,解析结果保留 `90 天`,聚合表保留 `180 天+` - V1 先使用单 PostgreSQL 主实例;若读压升高,优先增加只读副本而不是立即拆库 #### 13.13.4 限流、队列保护与熔断 - `gateway` 层增加基于 Redis 的租户级令牌桶限流,维度为 `tenant_id + route_group` - `tenant-api` 在任务提交前校验:套餐额度、租户当日提交量、当前排队深度、模型通道状态 - `worker-generate` 对下游 LLM 调用统一使用 `context.WithTimeout(30s)`,并以 `semaphore` 控制单 consumer 组最大并发,V1 默认建议 `50` - 交互式生成、批量生成、监控采集使用独立令牌桶;`worker-analytics` 默认只占用小比例低优先级通道,不能反压用户实时生成 - `worker-generate` 与 `worker-analytics` 的上游调用按 `3s / 10s / 30s` 做有限退避重试;熔断打开后只允许少量探测请求恢复 - `worker-knowledge` 的 Embedding 请求按 chunk 批量提交,建议单次 `16 ~ 32` 个 chunk,失败时自动拆批重试 - RabbitMQ 为生成队列配置最大长度和溢出策略,超过阈值时拒绝低优先级批量任务 - 平台端的强制重试、强制补量、限流豁免必须写审计日志 #### 13.13.5 Redis 缓存与对象存储分发策略 - 工作台聚合、趋势图、高频问题、引用排行等热点查询使用 `TTL + 抖动 + 异步刷新` - 对不存在的数据维度使用空值缓存,避免缓存穿透 - 高热点品牌数据在凌晨批量预热,避免白天冷启动击穿数据库 - 公有云部署推荐 `OSS + CDN`;私有化部署推荐 `MinIO + Nginx / CDN` - 图片、封面、知识库原文件通过带签名的对象存储 URL 输出,走 CDN 分发 - 已删除知识文档的对象文件按 `T+7` 清理,原始模型回答按监控策略保留 `30 ~ 90 天` - 发布请求/响应原始 payload 建议按审计需求保留 `30 ~ 90 天`,并由 GC 任务定期扫描孤儿文件 #### 13.13.6 配置管理与动态加载 - V1 配置层级采用:`base YAML -> 环境变量覆盖 -> 动态配置覆盖` - 动态配置仅用于可热更新项:限流阈值、功能开关、模型通道权重、adapter 开关、轮询/SSE 策略 - 结构性配置如数据库 DSN、MQ 地址、端口等仍通过重启生效,避免隐藏复杂度 - 所有动态配置变更进入 `config_change_logs` #### 13.13.7 Sponge 使用原则 - `sponge` 仅作为脚手架初始化工具使用,不采用其默认的业务 `handler/service/dao` 全量代码生成 - 如需复用少量样板代码,生成代码也必须按本文分层映射:`handler -> transport`、`service/logic -> app`、`dao -> repository`、`domain` 由业务手工维护 - `tenant` 与 `platform` 的双域拆分优先于代码生成习惯,架构设计始终先于框架约束 #### 13.13.8 Migration 与 Schema 变更策略 - V1 推荐统一使用 `golang-migrate` 管理 Schema 版本,目录固定为 `server/migrations/` - 命名规则建议:`YYYYMMDDHHMMSS_description.up.sql` 与对应 `down.sql` - 线上 DDL 采用 expand / migrate / contract 三阶段,避免单次发布中直接删列、改类型或重建大索引 - 分区表、索引和长耗时 DDL 必须走预发演练;高风险变更在低峰窗口执行并保留回滚脚本 #### 13.13.9 租户隔离与关键事务边界 - Repository 层必须提供 `TenantScope(ctx)` 或等价封装,租户侧查询默认自动注入 `tenant_id` - 平台侧跨租户查询只允许出现在 `platform/*` 域;禁止在租户域直接手写绕过租户条件的 SQL - CI 应增加静态检查或代码评审规则,重点扫描缺少 `tenant_id` 过滤的查询 - 关键事务边界至少包括:任务提交预扣额度、Worker 成功确认额度、Worker 失败退还额度、插件回调幂等落库 #### 13.13.10 错误码、日志与链路追踪 - 所有进程统一使用结构化 JSON 日志,建议使用 `zap` - `gateway` 为入口请求生成 `request_id`;若上游已带可信 `request_id` 则复用,并同时补充内部 `trace_id` - API -> MQ -> Worker 全链路透传 `request_id`、`trace_id`、`tenant_id`、`task_batch_id` - RabbitMQ 消息头必须包含上述追踪字段,Worker 落日志时原样打印 - V1 最低要求是“统一错误码 + 结构化日志 + `request_id` 贯通”;V1.5 再引入 OpenTelemetry / Jaeger - 所有告警规则统一绑定 `service`、`queue`、`tenant_scope`、`error_code` 标签,便于聚合排查 #### 13.13.11 本地开发、归档与运维模板 - 本地开发默认模式为“中间件容器化,Go 服务本地运行”,避免 `docker compose up` 同时拉起全部业务进程 - 提供统一的 `make dev-init`、`make dev-api`、`make dev-workers` 或等价任务入口,降低新人启动门槛 - 4 类 Worker 保持独立二进制,但共享同一套容器基座、健康检查协议、日志格式和 Helm 模板 - 审计表与监控表分区需配套归档脚本或定时作业,按月导出历史分区并清理超期数据 - 对象存储 GC、分区归档、死信队列巡检建议统一纳入 `scheduler` 的低频运维作业或独立运维 CronJob ## 14. 最终建议 如果当前目标是尽快落地并保持后续可扩展,最推荐的方案是: - 前端采用双应用:`apps/admin-web` 与 `apps/ops-admin-web` - V1 同步建设执行端:`apps/browser-extension` - 共享能力全部沉淀到 `packages/*` - 后端采用 `gateway + tenant-api + platform-api + scheduler + 多 Worker` 结构 - 统一使用 `PostgreSQL + Redis + RabbitMQ + Qdrant + 对象存储` - 权限严格按 `platform_role` 与 `tenant_role` 分层 - 高风险操作统一纳入审计 这个方案的优点是: - 前端边界清晰 - 后端复杂度可控 - 权限模型不混乱 - 既适合 V1,也方便未来演进到更细的服务拆分