# content 下一步工作与上下游依赖 > 模块:content(内容域服务,Textbook/Chapter/KnowledgeGraph/Question 四 Service,端口 HTTP 3005 / gRPC 50054) > 负责人:ai09 > 更新日期:2026-07-13(P4–P6+ 全部完成,Docker 本地测试通过) > 关联文档:[02-architecture-design.md](./02-architecture-design.md)、[content_contract.md](../../../docs/architecture/issues/contracts/content_contract.md)、[content_workline.md](../../../docs/architecture/issues/worklines/content_workline.md) --- ## 1. 模块当前状态 content 模块已完成 P4–P6+ 全部批次,提供 Textbook / Chapter / KnowledgeGraph / Question 四个 Service 共 22 个 RPC,本地 Docker 镜像构建与运行验证通过(非 mock 数据),ES 全文检索、Neo4j 知识图谱、审核工作流状态机、Outbox 事件驱动全部联调通过。 ### 1.1 服务能力概览 | Service | RPC 数量 | 核心能力 | | --------------------- | -------- | --------------------------------------------------------------- | | TextbookService | — | 教材 CRUD、教材树管理、归档、版本查询 | | ChapterService | — | 章节 CRUD、章节目录树 | | KnowledgeGraphService | — | 知识点 CRUD、知识图谱(Neo4j)、学习路径、前置依赖、可视化 | | QuestionService | — | 题目 CRUD、ES 全文检索、审核工作流状态机、AI 批量出题(待联调) | | **合计** | **22** | 4 Service | ### 1.2 P5 完成项(ES 集成) | 验证项 | 状态 | 说明 | | -------------------------------------- | ---- | -------------------------------------------------------------- | | Elasticsearch 容器就绪 | ✅ | 本地 Docker edu-es 已就绪 | | ES config 模块 | ✅ | `src/config/elasticsearch.ts`(惰性初始化 + ik→standard 回退) | | ES Sync Worker(Kafka 消费 → ES 索引) | ✅ | `src/shared/sync/es-sync.worker.ts`(event_id 去重 + 软失败) | | SearchQuestions API 接入 ES | ✅ | ES 优先,MySQL LIKE 降级 | | content_questions 索引映射 | ✅ | `ensureQuestionIndex()` 幂等创建,ik 不可用时回退 standard | | /readyz ES 索引存在性检查 | ✅ | degraded 而非 error | ### 1.3 P6+ 完成项 | 验证项 | 状态 | 说明 | | ------------------------- | ---- | ------------------------------------------------------------------------------------------- | | Question 审核工作流状态机 | ✅ | draft→pending_review→published/rejected→archived,非法转换拦截 | | 知识图谱可视化 API | ✅ | `GET /knowledge-graph/visualization`,Neo4j 优先 + MySQL 降级 | | 教材版本管理 | ✅ | `GET /textbooks/versions` + `POST /textbooks/:id/archive` | | 可观测性硬化 | ✅ | 5 个 Prometheus 指标(outbox_pending / neo4j_lag / es_lag / search_total / search_latency) | | /readyz Outbox 积压检查 | ✅ | pending > 100 → degraded | ### 1.4 本地 Docker 验证结果(2026-07-13) 测试环境:本地 Docker(edu-mysql + edu-neo4j + edu-es + edu-kafka + edu-redis + edu-content-test,均接入 `edu-full_default` 网络) ``` 镜像:edu/content:test 容器:edu-content-test(DEV_MODE=true) 测试 1:健康检查 GET /healthz → {"status":"ok","service":"content"} ✅ GET /readyz → {"status":"ok","dependencies":[mysql:ok, neo4j:ok, kafka:ok, outbox:ok(0), elasticsearch:ok]} ✅ 测试 2:REST CRUD(全部通过) POST /textbooks → 创建教材 ✅ (id=l9oo0iycnxlguqvhskjhrksa) POST /chapters → 创建章节 ✅ (id=qdry24sm4ni2lrdf0fe7is2k) POST /knowledge-points → 创建知识点 ✅ (id=tuuv90gloo7kf2x1al0b1b6g) POST /questions → 创建题目 ✅ (id=ellr9gi1mnb9ir7ifxukhixs) GET /questions/:id → 读取题目 ✅ (status=draft) GET /questions?knowledgePointId=... → 列表查询 ✅ (count=1) 测试 3:ES 全文检索 GET /questions/search?q=3 → total=1 ✅ (ES 索引命中) GET /questions/search?q=苹果 → total=0 (standard 分析器中文按字切分,IK 插件可用时改善) 测试 4:审核工作流状态机 POST /questions/:id/submit-review → draft→pending_review ✅ POST /questions/:id/approve → pending_review→published ✅ POST /questions/:id/archive → published→archived ✅ POST /questions/:id/approve → 非法转换正确拒绝 ✅ (CONTENT_VALIDATION_ERROR) 测试 5:Outbox 事件驱动 content_outbox_events 表 8 条事件,全部 status=published, retry_count=0 ✅ 事件类型:textbook.created, chapter.created, knowledge_point.created, question.created, question.updated×2, question.published, textbook.archived 测试 6:Neo4j 知识图谱同步 Neo4j KnowledgePoint 节点已创建 ✅ (id=tuuv90gloo7kf2x1al0b1b6g, difficulty=2) GET /knowledge-graph/visualization → nodes=1, edges=0 ✅ 测试 7:教材归档 POST /textbooks/:id/archive → status=archived ✅ 测试 8:Prometheus 指标 GET /metrics → content_outbox_pending_total=0, content_neo4j_sync_lag_ms=0, content_es_sync_lag_ms=0, content_question_search_total{source="es"} ✅ ``` --- ## 2. 上游依赖(content 依赖谁) ### 2.1 MySQL(基础设施)— P0 必需 | 项 | 内容 | | -------- | -------------------------------------------------------------------------------------------- | | 端点 | `mysql://edu-mysql:3306/next_edu_cloud` | | 用途 | 主数据存储(textbooks / chapters / knowledge_points / questions / content_outbox_events 表) | | 状态 | ✅ 本地 Docker edu-mysql 已就绪 | | 环境变量 | `DATABASE_URL` | ### 2.2 Neo4j(基础设施)— P0 必需 | 项 | 内容 | | -------- | ---------------------------------------------------------- | | 端点 | `bolt://edu-neo4j:7687` | | 用途 | 知识图谱存储(KnowledgePoint 节点 + PREREQUISITE_OF 关系) | | 状态 | ✅ 本地 Docker edu-neo4j 已就绪 | | 环境变量 | `NEO4J_URL`、`NEO4J_PASSWORD` | ### 2.3 Kafka(基础设施)— P0 必需 | 项 | 内容 | | -------- | ------------------------------------------------------------------------------- | | 端点 | `kafka:29092` | | 用途 | Outbox 事件发布(4 个聚合 topic)+ Neo4j Sync Worker 消费 + ES Sync Worker 消费 | | 状态 | ✅ 本地 Docker edu-kafka 已就绪 | | 环境变量 | `KAFKA_BROKERS` | ### 2.4 Redis(基础设施)— P1 可选 | 项 | 内容 | | -------- | ---------------------------------------------------------------- | | 端点 | `redis://edu-redis:6379` | | 用途 | 缓存(教材树 / 知识点树读多写少场景),env.ts 已预留 `REDIS_URL` | | 状态 | ✅ 本地 Docker edu-redis 已就绪 | | 环境变量 | `REDIS_URL` | ### 2.5 Elasticsearch(基础设施)— P5 必需 | 项 | 内容 | | -------- | ------------------------------------------ | | 端点 | `http://edu-es:9200` | | 用途 | 题目全文检索(content_questions 索引) | | 状态 | ✅ 本地 Docker edu-es 已就绪(profile p5) | | 环境变量 | `ES_URL` | ### 2.6 ai 服务(ai12 负责)— P5 联调 | # | 依赖项 | 用途 | 状态 | | --- | ------------------------------ | -------------------------------------------------------- | ----------------- | | 1 | gRPC `GenerateQuestion` :50058 | AI 批量出题(QuestionService.BatchCreateQuestions 联调) | ⏳ 待 ai 服务就绪 | **关键环境变量**: - `AI_GRPC_TARGET=ai:50058`(待联调阶段配置) --- ## 3. 下游依赖(谁依赖 content) ### 3.1 teacher-bff(ai03 负责)— gRPC :50054 | # | 依赖项 | 用途 | 状态 | | --- | --------------------------------------------------- | -------------------- | ---------------------- | | 1 | gRPC `GetLearningPath(studentId, subjectId)` :50054 | `knowledgePath` 查询 | ✅ content gRPC 已就绪 | | 2 | gRPC `ListTextbooks(subjectId, gradeId)` :50054 | 教材列表 | ✅ content gRPC 已就绪 | | 3 | gRPC `ListChapters(textbookId)` :50054 | 章节目录 | ✅ content gRPC 已就绪 | ### 3.2 student-bff(ai04 负责)— gRPC :50054 | # | 依赖项 | 用途 | 状态 | | --- | ---------------------------------- | ------------ | ----------------------------------------- | | 1 | gRPC `ListTextbooks` :50054 | 学生浏览教材 | ✅ content gRPC 已就绪 | | 2 | gRPC `ListChapters` :50054 | 学生浏览章节 | ✅ content gRPC 已就绪 | | 3 | gRPC `GetLearningPath` :50054 | 学生学习路径 | ✅ content gRPC 已就绪 | | 4 | gRPC `SearchQuestions` :50054 | 题目检索 | ✅ content ES 已就绪,待 student-bff 联调 | | 5 | gRPC `BatchCreateQuestions` :50054 | AI 出题 | ⏳ 待 ai 服务就绪后联调 | ### 3.3 parent-bff(ai05 负责)— gRPC :50054 | # | 依赖项 | 用途 | 状态 | | --- | ------------------------------ | -------------------- | ---------------------- | | 1 | gRPC `ListTextbooks` :50054 | 家长查看孩子教材 | ✅ content gRPC 已就绪 | | 2 | gRPC `ListChapters` :50054 | 家长查看孩子章节 | ✅ content gRPC 已就绪 | | 3 | gRPC `GetPrerequisites` :50054 | 孩子学习路径前置依赖 | ✅ content gRPC 已就绪 | | 4 | gRPC `GetLearningPath` :50054 | 孩子学习路径 | ✅ content gRPC 已就绪 | ### 3.4 data-ana(ai11 负责)— Kafka 消费 | # | 依赖项 | 用途 | 状态 | | --- | ----------------------------------------------- | ------------------ | ----------------------- | | 1 | 消费 topic `edu.content.knowledge_point.events` | 分析知识点难度分布 | ✅ content Kafka 已就绪 | | 2 | 消费 topic `edu.content.question.events` | 题目来源统计 | ✅ content Kafka 已就绪 | ### 3.5 api-gateway(ai01 负责)— HTTP REST :3005 | 能力 | 配置 | 状态 | | ----------------------------------- | -------------------- | ------------------------- | | `/api/v1/textbooks` 反向代理 | → content:3005 | ✅ api-gateway 已配置路由 | | `/api/v1/chapters` 反向代理 | → content:3005 | ✅ api-gateway 已配置路由 | | `/api/v1/knowledge-points` 反向代理 | → content:3005 | ✅ api-gateway 已配置路由 | | `/api/v1/questions` 反向代理 | → content:3005 | ✅ api-gateway 已配置路由 | | `GET /healthz` 端点 | /readyz 下游健康检查 | ✅ 已实现 | ### 3.6 ai 服务(ai12 负责)— Kafka 消费 | # | 依赖项 | 用途 | 状态 | | --- | ---------------------------------------- | ----------------------- | ----------------------- | | 1 | 消费 topic `edu.content.question.events` | AI 出题时获取知识点信息 | ✅ content Kafka 已就绪 | --- ## 4. 环境变量清单 | 变量 | 必填 | 示例值 | 说明 | | ----------------------------- | ---- | ---------------------------------------------------- | ------------------ | | `PORT` | 是 | `3005` | HTTP 监听端口 | | `GRPC_PORT` | 是 | `50054` | gRPC 监听端口 | | `DATABASE_URL` | 是 | `mysql://edu:changeme@edu-mysql:3306/next_edu_cloud` | MySQL 连接 | | `REDIS_URL` | 否 | `redis://edu-redis:6379` | Redis 缓存 | | `NEO4J_URL` | 否 | `bolt://edu-neo4j:7687` | Neo4j 连接 | | `NEO4J_PASSWORD` | 否 | `changeme` | Neo4j 密码 | | `ES_URL` | 否 | `http://edu-es:9200` | Elasticsearch 连接 | | `KAFKA_BROKERS` | 是 | `kafka:29092` | Kafka broker | | `JWT_SECRET` | 否 | — | JWT 密钥 | | `DEV_MODE` | 否 | `false` | 开发模式 | | `OTEL_EXPORTER_OTLP_ENDPOINT` | 否 | `http://otel-collector:4318` | OTLP 端点 | | `LOG_LEVEL` | 否 | `info` | 日志级别 | --- ## 5. 剩余工作 | # | 工作项 | 阶段 | 状态 | | --- | ---------------------------------------------- | ---- | ----------------- | | 1 | ES 集成(config + sync worker + search API) | P5 | ✅ 完成 | | 2 | Question 审核工作流状态机 | P6+ | ✅ 完成 | | 3 | 知识图谱可视化 API | P6+ | ✅ 完成 | | 4 | 教材版本管理 | P6+ | ✅ 完成 | | 5 | 可观测性硬化(Prometheus 指标 + readyz 检查) | P6+ | ✅ 完成 | | 6 | AI 批量出题联调(BatchCreateQuestions + ai12) | 联调 | ⏳ 待 ai 服务就绪 | content 模块自身功能已全部完成,无剩余开发任务。唯一待办为 ai 服务(ai12)就绪后的 AI 出题联调。 --- ## 6. Docker 本地测试 ### 6.1 镜像构建 ```bash docker build -t edu/content:test -f services/content/Dockerfile . ``` ### 6.2 容器启动 ```bash docker run -d \ --name edu-content-test \ --network edu-full_default \ -p 3005:3005 -p 50054:50054 \ -e DATABASE_URL=mysql://edu:changeme@edu-mysql:3306/next_edu_cloud \ -e NEO4J_URL=bolt://edu-neo4j:7687 \ -e NEO4J_PASSWORD=changeme \ -e ES_URL=http://edu-es:9200 \ -e KAFKA_BROKERS=kafka:29092 \ -e REDIS_URL=redis://edu-redis:6379 \ -e NODE_ENV=production \ -e DEV_MODE=true \ edu/content:test ``` --- ## 7. 关键文件路径 | 文件 | 用途 | | -------------------------------------------------------- | ----------------------------- | | `packages/shared-proto/proto/content.proto` | gRPC 契约(22 RPC) | | `packages/shared-proto/proto/events.proto` | 事件契约(4 content message) | | `services/content/src/main.ts` | 服务入口 | | `services/content/src/app.module.ts` | NestJS 模块注册 | | `services/content/src/grpc/` | 4 个 gRPC controller | | `services/content/src/shared/outbox/` | Outbox 模式实现 | | `services/content/src/shared/sync/neo4j-sync.worker.ts` | Neo4j 异步同步 | | `services/content/Dockerfile` | Docker 构建 | | `docs/architecture/issues/contracts/content_contract.md` | 契约文档 | | `docs/architecture/issues/worklines/content_workline.md` | 工作排期 | --- **本文件由 ai09 维护,上游/下游工作项请各负责 AI 完成后通知 ai09 更新状态。**