diff --git a/.revision-progress b/.revision-progress new file mode 100644 index 0000000..ba495fa --- /dev/null +++ b/.revision-progress @@ -0,0 +1,2 @@ +# zhuangang 结构化内容改造进度(每完成一个阶段追加一行;重启时跳过已完成阶段) +phase1 done 2026-10-23 15:05:36:目录设计、CONTRIBUTING、schema、tools/build_catalog.py、run_examples.py、check_sensitive.py、31 个技术栈首页骨架、周文件 frontmatter diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..86a7edd --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,140 @@ +# 内容规范(CONTRIBUTING) + +本仓库是**结构化的学习内容**:既能直接在 Git 平台上阅读,也能被以后的在线学习平台导入。所有新增、修改的内容都按本规范写,提交前运行校验脚本。 + +## 1. 目录结构 + +```text +zhuangang/ +├── README.md # 仓库入口 +├── CONTRIBUTING.md # 本文件:内容规范 +├── catalog.json # 自动生成的内容目录(不要手改) +├── schema/frontmatter.schema.json +├── tools/ +│ ├── build_catalog.py # 校验 + 生成 catalog.json +│ ├── run_examples.py # 运行示例代码 +│ └── check_sensitive.py # 提交前脱敏检查(第 8 周建立) +├── plan/ # 16 周学习计划(日程),链接到专题,不重复讲概念 +│ ├── README.md # 总纲 +│ └── weekNN-*.md # type: week +├── topics/ # 专项学习:按领域 / 技术栈组织 +│ ├── index.md +│ └── // +│ ├── index.md # type: index,技术栈首页:学习路线、课程列表 +│ ├── NN-.md # type: lesson,课程,NN 是顺序 +│ ├── scenarios/.md # type: scenario,该技术栈的企业场景 +│ ├── interview.md # type: interview,分级面试题 +│ └── examples/ # 可运行的示例代码 +└── scenarios/ # 跨技术栈的企业服务场景(type: scenario,domain: cross) + ├── index.md + └── .md +``` + +- `domain` 取值:`backend`(Go、数据库、缓存、消息队列、微服务)、`devops`(Docker、Nginx、Linux、CI/CD、Git)、`python`、`ai`(RAG、Agent 等)、`frontend`、`cross`(跨栈场景)、`plan`(计划)。 +- `` 是技术栈标识,只用小写字母、数字和 `-`,例如 `redis`、`grpc-microservices`、`fe-testing-perf`。 + +## 2. frontmatter + +每个 `.md` 文件(`examples/` 下的除外)第一行开始是 frontmatter。为了让校验脚本不依赖第三方库,**只允许两种写法**:`键: 标量` 和 `键: [a, b, c]`(列表写在一行)。 + +```yaml +--- +id: backend.redis.cache-patterns +title: 缓存模式:旁路缓存与穿透、击穿、雪崩 +type: lesson +domain: backend +stack: [redis] +tags: [缓存, 高并发, 一致性] +level: intermediate +prerequisites: [backend.redis.data-structures] +est_hours: 2 +related: [backend.redis.interview, scenario.flash-sale] +week: [3, 14] +order: 2 +--- +``` + +| 字段 | 必填 | 说明 | +| --- | --- | --- | +| `id` | 是 | 全局唯一、**发布后不再修改**(平台用它做进度记录和链接)。格式:小写字母数字,用 `.` 分段 | +| `title` | 是 | 标题 | +| `type` | 是 | `index` / `lesson` / `scenario` / `interview` / `project` / `week` | +| `domain` | 是 | 见上 | +| `stack` | lesson、scenario、interview 必填 | 列表;跨栈场景写多个 | +| `level` | lesson、scenario、interview 必填 | `basic`(基础)/ `intermediate`(进阶)/ `advanced`(高级) | +| `tags` | 否 | 关键词,平台用于搜索 | +| `prerequisites` | 否 | 先修内容的 id | +| `related` | 否 | 相关内容的 id | +| `est_hours` | 否 | 预计学习小时数 | +| `week` | 否 | 在 16 周计划的哪几周用到(1~16) | +| `order` | 否 | 同一技术栈内的排序 | + +**id 约定**: + +| 内容 | id 格式 | 例子 | +| --- | --- | --- | +| 技术栈首页 | `..index` | `backend.redis.index` | +| 课程 | `..` | `backend.redis.cache-patterns` | +| 技术栈场景 | `..scenario.` | `backend.redis.scenario.leaderboard` | +| 面试题 | `..interview` | `backend.redis.interview` | +| 跨栈场景 | `scenario.` | `scenario.flash-sale` | +| 计划 | `plan.index`、`plan.weekNN` | `plan.week03` | + +## 3. 各类型的写法 + +### 课程(lesson) + +必须包含以下二级标题(标题里包含这些词即可,可以加后缀): + +- `## 解释说明`:是什么、为什么,用大白话;和 JS / 前端经验类比更好。 +- `## 案例`:在真实业务里用在哪。 +- `## 代码示例`:最小、正确、能运行;代码块写语言标记。较长的完整示例放进 `examples/`,在正文里链接。 +- `## 易错点`:常见错误和原因。 +- 可选:`## 面试常问`(链接到本技术栈的 `interview.md`)、`## 延伸阅读`。 + +### 场景(scenario) + +企业服务场景解决方案,必须包含: + +- `## 业务背景与问题` +- `## 约束`:规模、性能、成本、合规、团队等限制条件 +- `## 方案设计`:架构图(mermaid)、关键流程、数据模型 +- `## 关键代码` +- `## 取舍`:为什么选这个方案、放弃了什么 +- `## 易错点` +- `## 面试怎么讲`:一段 1~2 分钟的讲法 + 可能的追问 + +### 面试题(interview) + +- 每道题一个三级标题,**必须**以级别开头:`### 【基础】…`、`### 【进阶】…`、`### 【场景题】…`。校验脚本按这个格式统计题数。 +- 题目下面写 `**参考答案**`,再写 `**追问**`(常见的追问和要点)。 +- 能结合项目的写上“在本计划的哪个项目里体现”。 + +### 计划(week) + +- 日程安排:每天的任务、要建的文件、运行方式、完成标准。 +- 概念讲解放在专题里,计划文件用链接引用,不重复写。项目的分步实现代码保留在计划文件里(type 仍为 `week`)。 + +## 4. 写作规则 + +1. 中文写作,术语第一次出现时附英文。 +2. **代码必须正确**:能运行的示例放进 `examples/` 并能被 `tools/run_examples.py` 跑通;需要外部服务的在文件开头写 `不自动运行`,并说明怎么手动运行。 +3. 更新快的框架(LangChain、LangGraph、MCP、Vite、Next.js、Nuxt 等)标注“以官方文档为准”并附链接,写明验证时的版本。 +4. **脱敏**:不出现公司内部项目名、代码、接口路径、表名、内网地址、密钥、客户数据。场景都用通用的业务描述。 +5. 不编造数据:性能数字、统计数字必须注明来源,或写成“以实测为准”。 +6. 链接一律用相对路径,校验脚本会检查链接是否存在。 + +## 5. 提交前 + +```bash +python3 tools/build_catalog.py # 校验并更新 catalog.json +python3 tools/run_examples.py # 运行示例(可加关键词只跑部分,例如 redis) +python3 tools/check_sensitive.py # 脱敏检查(如果已经按第 8 周装好钩子,会自动执行) +``` + +## 6. 给学习平台的导入说明 + +- 以 `catalog.json` 为入口:`stacks` 是技术栈列表(含课程数、场景数、各级面试题数、示例路径),`items` 是全部内容(frontmatter + 文件路径 + 二级标题列表 + 面试题统计)。 +- 内容正文就是 Markdown 文件本身(去掉 frontmatter);mermaid 图需要前端渲染。 +- 学习进度按 `id` 记录;`prerequisites` 可以生成学习路线图,`week` 可以生成日程视图。 +- 面试题可以按 `### 【级别】` 标题切分成单题,`**参考答案**` 和 `**追问**` 是固定的小标题。 diff --git a/README.md b/README.md index 74293fe..3f732ff 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,36 @@ # zhuangang · 转岗学习仓库 -16 周转岗计划和全部练习代码:Python AI 应用 / Agent 开发为主(RAG、LangGraph、MCP、评测),Go 全栈为辅。 +16 周转岗计划 + 按技术栈组织的专项学习内容 + 企业场景方案 + 分级面试题 + 可运行示例。方向:Python AI 应用 / Agent 开发为主(RAG、LangGraph、MCP、评测),Go 全栈为辅。 -从 [plan/README.md](plan/README.md) 开始看:里面有总路线、岗位要求对照、每周计划文件和进度记录。 +## 从哪里开始 + +| 我想…… | 看这里 | +| --- | --- | +| 按 16 周计划一步步学 | [plan/README.md](plan/README.md)(总纲、进度记录),每周文件链接到对应专题 | +| 单独补某个技术栈 | [topics/index.md](topics/index.md)(31 个技术栈:课程、场景、面试题、示例) | +| 看企业里的综合方案 | [scenarios/index.md](scenarios/index.md)(客服知识库、工单、审批流、秒杀、多租户……) | +| 准备面试 | 每个技术栈目录下的 `interview.md`(基础 / 进阶 / 场景题,带参考答案和追问) | +| 写新内容 / 做学习平台 | [CONTRIBUTING.md](CONTRIBUTING.md)(目录、frontmatter、各类型写法)、`catalog.json`(自动生成的内容目录) | + +## 目录 + +```text +plan/ 16 周日程(type: week),链接到专题,不重复讲概念 +topics/ 专项学习:<领域>/<技术栈>/{index.md, NN-课程.md, scenarios/, interview.md, examples/} +scenarios/ 跨技术栈的企业服务场景 +tools/ build_catalog.py(校验 + 生成目录)、run_examples.py(运行示例)、check_sensitive.py(脱敏检查) +schema/ frontmatter 的 JSON Schema +catalog.json 内容目录(由 tools/build_catalog.py 生成,不要手改) +``` + +练习项目(`go-learning/`、`todo-api/`、`task-board/`、`py-learning/`、`rag-qa/`、`web/`、`agent-mini/`、`backend-extend/`、`career/` 等)按计划逐周建在仓库根目录。 + +## 常用命令 + +```bash +python3 tools/build_catalog.py # 校验所有内容并更新 catalog.json +python3 tools/run_examples.py redis # 运行某个技术栈的示例代码 +python3 tools/check_sensitive.py --self-test +``` + +克隆:`git clone ssh://wsk@git.gozeros.com:30023/wsk/zhuangang.git`(SSH 不通时用 `https://git.gozeros.com/wsk/zhuangang.git`)。 diff --git a/catalog.json b/catalog.json new file mode 100644 index 0000000..ebb07d1 --- /dev/null +++ b/catalog.json @@ -0,0 +1,1676 @@ +{ + "schema_version": 1, + "generated_by": "tools/build_catalog.py", + "stacks": [ + { + "stack": "agent-ops", + "domain": "ai", + "title": "Agent 记忆、评测与可观测性", + "index": "topics/ai/agent-ops/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "function-calling", + "domain": "ai", + "title": "Function Calling 工具调用", + "index": "topics/ai/function-calling/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "langchain", + "domain": "ai", + "title": "LangChain", + "index": "topics/ai/langchain/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "langgraph", + "domain": "ai", + "title": "LangGraph", + "index": "topics/ai/langgraph/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "lowcode", + "domain": "ai", + "title": "Dify / Coze 低代码平台", + "index": "topics/ai/lowcode/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "mcp", + "domain": "ai", + "title": "MCP 模型上下文协议", + "index": "topics/ai/mcp/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "prompt-engineering", + "domain": "ai", + "title": "提示词与上下文工程", + "index": "topics/ai/prompt-engineering/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "rag", + "domain": "ai", + "title": "RAG 检索增强生成", + "index": "topics/ai/rag/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "vector-db", + "domain": "ai", + "title": "向量数据库", + "index": "topics/ai/vector-db/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "gin", + "domain": "backend", + "title": "Gin Web 框架", + "index": "topics/backend/gin/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "go", + "domain": "backend", + "title": "Go 语言", + "index": "topics/backend/go/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "grpc-microservices", + "domain": "backend", + "title": "gRPC 与微服务", + "index": "topics/backend/grpc-microservices/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "mq", + "domain": "backend", + "title": "消息队列(RabbitMQ / Kafka)", + "index": "topics/backend/mq/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "mysql", + "domain": "backend", + "title": "MySQL", + "index": "topics/backend/mysql/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "postgresql", + "domain": "backend", + "title": "PostgreSQL", + "index": "topics/backend/postgresql/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "redis", + "domain": "backend", + "title": "Redis", + "index": "topics/backend/redis/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "cicd", + "domain": "devops", + "title": "CI/CD", + "index": "topics/devops/cicd/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "docker", + "domain": "devops", + "title": "Docker 与 Compose", + "index": "topics/devops/docker/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "git", + "domain": "devops", + "title": "Git", + "index": "topics/devops/git/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "linux", + "domain": "devops", + "title": "Linux 运维基础", + "index": "topics/devops/linux/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "nginx", + "domain": "devops", + "title": "Nginx", + "index": "topics/devops/nginx/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "fe-testing-perf", + "domain": "frontend", + "title": "前端测试与性能", + "index": "topics/frontend/fe-testing-perf/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "react", + "domain": "frontend", + "title": "React", + "index": "topics/frontend/react/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "ssr", + "domain": "frontend", + "title": "SSR(Nuxt / Next.js)", + "index": "topics/frontend/ssr/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "typescript", + "domain": "frontend", + "title": "TypeScript", + "index": "topics/frontend/typescript/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "vite", + "domain": "frontend", + "title": "Vite", + "index": "topics/frontend/vite/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "vue", + "domain": "frontend", + "title": "Vue 3 + Pinia + Router", + "index": "topics/frontend/vue/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "webpack", + "domain": "frontend", + "title": "Webpack", + "index": "topics/frontend/webpack/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "asyncio", + "domain": "python", + "title": "asyncio 异步编程", + "index": "topics/python/asyncio/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "fastapi", + "domain": "python", + "title": "FastAPI", + "index": "topics/python/fastapi/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + }, + { + "stack": "python", + "domain": "python", + "title": "Python 语言", + "index": "topics/python/python/index.md", + "lessons": 0, + "scenarios": 0, + "interview_questions": { + "基础": 0, + "进阶": 0, + "场景题": 0 + }, + "examples": [] + } + ], + "items": [ + { + "id": "ai.agent-ops.index", + "title": "Agent 记忆、评测与可观测性", + "type": "index", + "domain": "ai", + "stack": [ + "agent-ops" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 12, + 13 + ], + "order": null, + "path": "topics/ai/agent-ops/index.md", + "sections": [] + }, + { + "id": "ai.function-calling.index", + "title": "Function Calling 工具调用", + "type": "index", + "domain": "ai", + "stack": [ + "function-calling" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 10 + ], + "order": null, + "path": "topics/ai/function-calling/index.md", + "sections": [] + }, + { + "id": "ai.langchain.index", + "title": "LangChain", + "type": "index", + "domain": "ai", + "stack": [ + "langchain" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 6, + 11 + ], + "order": null, + "path": "topics/ai/langchain/index.md", + "sections": [] + }, + { + "id": "ai.langgraph.index", + "title": "LangGraph", + "type": "index", + "domain": "ai", + "stack": [ + "langgraph" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 11, + 12 + ], + "order": null, + "path": "topics/ai/langgraph/index.md", + "sections": [] + }, + { + "id": "ai.lowcode.index", + "title": "Dify / Coze 低代码平台", + "type": "index", + "domain": "ai", + "stack": [ + "lowcode" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 13 + ], + "order": null, + "path": "topics/ai/lowcode/index.md", + "sections": [] + }, + { + "id": "ai.mcp.index", + "title": "MCP 模型上下文协议", + "type": "index", + "domain": "ai", + "stack": [ + "mcp" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 10, + 11 + ], + "order": null, + "path": "topics/ai/mcp/index.md", + "sections": [] + }, + { + "id": "ai.prompt-engineering.index", + "title": "提示词与上下文工程", + "type": "index", + "domain": "ai", + "stack": [ + "prompt-engineering" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 5, + 11, + 13 + ], + "order": null, + "path": "topics/ai/prompt-engineering/index.md", + "sections": [] + }, + { + "id": "ai.rag.index", + "title": "RAG 检索增强生成", + "type": "index", + "domain": "ai", + "stack": [ + "rag" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 5, + 6 + ], + "order": null, + "path": "topics/ai/rag/index.md", + "sections": [] + }, + { + "id": "ai.vector-db.index", + "title": "向量数据库", + "type": "index", + "domain": "ai", + "stack": [ + "vector-db" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 5, + 6 + ], + "order": null, + "path": "topics/ai/vector-db/index.md", + "sections": [] + }, + { + "id": "backend.gin.index", + "title": "Gin Web 框架", + "type": "index", + "domain": "backend", + "stack": [ + "gin" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 1, + 2, + 3 + ], + "order": null, + "path": "topics/backend/gin/index.md", + "sections": [] + }, + { + "id": "backend.go.index", + "title": "Go 语言", + "type": "index", + "domain": "backend", + "stack": [ + "go" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 1, + 2, + 3, + 14 + ], + "order": null, + "path": "topics/backend/go/index.md", + "sections": [] + }, + { + "id": "backend.grpc-microservices.index", + "title": "gRPC 与微服务", + "type": "index", + "domain": "backend", + "stack": [ + "grpc-microservices" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 14 + ], + "order": null, + "path": "topics/backend/grpc-microservices/index.md", + "sections": [] + }, + { + "id": "backend.mq.index", + "title": "消息队列(RabbitMQ / Kafka)", + "type": "index", + "domain": "backend", + "stack": [ + "mq" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 3, + 14 + ], + "order": null, + "path": "topics/backend/mq/index.md", + "sections": [] + }, + { + "id": "backend.mysql.index", + "title": "MySQL", + "type": "index", + "domain": "backend", + "stack": [ + "mysql" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 2, + 14 + ], + "order": null, + "path": "topics/backend/mysql/index.md", + "sections": [] + }, + { + "id": "backend.postgresql.index", + "title": "PostgreSQL", + "type": "index", + "domain": "backend", + "stack": [ + "postgresql" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 2, + 3, + 6 + ], + "order": null, + "path": "topics/backend/postgresql/index.md", + "sections": [] + }, + { + "id": "backend.redis.index", + "title": "Redis", + "type": "index", + "domain": "backend", + "stack": [ + "redis" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 3, + 6, + 14 + ], + "order": null, + "path": "topics/backend/redis/index.md", + "sections": [] + }, + { + "id": "devops.cicd.index", + "title": "CI/CD", + "type": "index", + "domain": "devops", + "stack": [ + "cicd" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 3, + 7, + 14 + ], + "order": null, + "path": "topics/devops/cicd/index.md", + "sections": [] + }, + { + "id": "devops.docker.index", + "title": "Docker 与 Compose", + "type": "index", + "domain": "devops", + "stack": [ + "docker" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 3, + 6, + 13, + 14 + ], + "order": null, + "path": "topics/devops/docker/index.md", + "sections": [] + }, + { + "id": "devops.git.index", + "title": "Git", + "type": "index", + "domain": "devops", + "stack": [ + "git" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 1, + 8, + 15 + ], + "order": null, + "path": "topics/devops/git/index.md", + "sections": [] + }, + { + "id": "devops.linux.index", + "title": "Linux 运维基础", + "type": "index", + "domain": "devops", + "stack": [ + "linux" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 14 + ], + "order": null, + "path": "topics/devops/linux/index.md", + "sections": [] + }, + { + "id": "devops.nginx.index", + "title": "Nginx", + "type": "index", + "domain": "devops", + "stack": [ + "nginx" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 3, + 7, + 14 + ], + "order": null, + "path": "topics/devops/nginx/index.md", + "sections": [] + }, + { + "id": "frontend.fe-testing-perf.index", + "title": "前端测试与性能", + "type": "index", + "domain": "frontend", + "stack": [ + "fe-testing-perf" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/fe-testing-perf/index.md", + "sections": [] + }, + { + "id": "frontend.react.index", + "title": "React", + "type": "index", + "domain": "frontend", + "stack": [ + "react" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/react/index.md", + "sections": [] + }, + { + "id": "frontend.ssr.index", + "title": "SSR(Nuxt / Next.js)", + "type": "index", + "domain": "frontend", + "stack": [ + "ssr" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/ssr/index.md", + "sections": [] + }, + { + "id": "frontend.typescript.index", + "title": "TypeScript", + "type": "index", + "domain": "frontend", + "stack": [ + "typescript" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/typescript/index.md", + "sections": [] + }, + { + "id": "frontend.vite.index", + "title": "Vite", + "type": "index", + "domain": "frontend", + "stack": [ + "vite" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/vite/index.md", + "sections": [] + }, + { + "id": "frontend.vue.index", + "title": "Vue 3 + Pinia + Router", + "type": "index", + "domain": "frontend", + "stack": [ + "vue" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/vue/index.md", + "sections": [] + }, + { + "id": "frontend.webpack.index", + "title": "Webpack", + "type": "index", + "domain": "frontend", + "stack": [ + "webpack" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 7 + ], + "order": null, + "path": "topics/frontend/webpack/index.md", + "sections": [] + }, + { + "id": "plan.index", + "title": "转岗计划总纲", + "type": "index", + "domain": "plan", + "stack": [], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [], + "order": null, + "path": "plan/README.md", + "sections": [ + "1. 背景、起点和目标", + "2. 技术栈(已确定)", + "3. 十六周总路线", + "4. 岗位要求对照", + "5. 学习原则和每周文件的写法", + "6. 时间不够怎么砍", + "7. 阶段 0~4 和五个学习重点", + "8. 案例卡模板(直接复制)", + "9. 每周节奏和戒律", + "10. 脱敏和保密", + "11. 简历和投递建议", + "12. 仓库结构、文件清单和换设备", + "13. 进度记录", + "14. 终点验收清单(全部勾选才算完结)" + ] + }, + { + "id": "plan.week01", + "title": "第 1 周:Go 基础 + Gin 写 REST 接口", + "type": "week", + "domain": "plan", + "stack": [ + "go", + "gin", + "git" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 1 + ], + "order": 1, + "path": "plan/week01-go-gin.md", + "sections": [ + "本周最终目录", + "第 1 天:环境、变量、函数和错误返回", + "第 2 天:切片、map、结构体、方法、接口", + "第 3 天:错误包装、并发、单元测试", + "第 4 天:从 net/http 到 Gin", + "第 5 天:分层:model / store / handler", + "第 6 天:中间件和接口测试", + "第 7 天:配置、优雅关机、接前端", + "本周自查清单" + ] + }, + { + "id": "plan.week02", + "title": "第 2 周:数据库(PostgreSQL 为主,兼顾 MySQL)+ 注册登录与 JWT", + "type": "week", + "domain": "plan", + "stack": [ + "go", + "gin", + "postgresql", + "mysql" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 2 + ], + "order": 2, + "path": "plan/week02-db-auth.md", + "sections": [ + "本周最终目录(在上周 `todo-api/backend` 基础上新增)", + "第 1 天:用 Docker 跑 PostgreSQL,写基础 SQL 和表设计", + "第 2 天:多表查询、索引、EXPLAIN", + "第 3 天:迁移和 Go 访问数据库(pgx)", + "第 4 天:事务、隔离级别、幂等写入", + "第 5 天:密码哈希和 JWT", + "第 6 天:注册、登录、鉴权中间件", + "第 7 天:配置切换、接口测试、集成测试、收尾", + "本周自查清单" + ] + }, + { + "id": "plan.week03", + "title": "第 3 周:项目一“团队任务看板”:权限 + Redis + 消息队列 + Docker 部署", + "type": "week", + "domain": "plan", + "stack": [ + "go", + "gin", + "postgresql", + "redis", + "mq", + "docker", + "nginx", + "cicd" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 3 + ], + "order": 3, + "path": "plan/week03-project1.md", + "sections": [ + "本周最终目录", + "第 1 天:看板建模和权限", + "第 2 天:看板和任务接口、拖动排序的事务", + "第 3 天:Redis 基础和缓存", + "第 4 天:限流和分布式锁", + "第 5 天:消息队列入门(Redis Streams),了解 RabbitMQ / Kafka", + "第 6 天:Docker、Compose、Nginx", + "第 7 天:部署到服务器 + CI + 收尾", + "本周自查清单" + ] + }, + { + "id": "plan.week04", + "title": "第 4 周:Python 速成(给 JS 开发者)+ FastAPI 基础", + "type": "week", + "domain": "plan", + "stack": [ + "python", + "asyncio", + "fastapi" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 4 + ], + "order": 4, + "path": "plan/week04-python.md", + "sections": [ + "本周最终目录", + "第 1 天:包管理和基础语法", + "第 2 天:类型标注、dataclass、Protocol、pytest", + "第 3 天:异常、上下文管理器、文件和日志", + "第 4 天:asyncio(本周最重要)", + "第 5 天:pydantic 和配置", + "第 6 天:httpx 异步请求、重试、测试替身", + "第 7 天:FastAPI(Uvicorn、依赖注入、中间件、鉴权、生命周期、SSE)", + "本周自查清单" + ] + }, + { + "id": "plan.week05", + "title": "第 5 周:RAG 知识库问答(上)——手写主流程", + "type": "week", + "domain": "plan", + "stack": [ + "asyncio", + "fastapi", + "rag", + "vector-db", + "prompt-engineering" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 5 + ], + "order": 5, + "path": "plan/week05-rag-1.md", + "sections": [ + "项目二总览", + "第 1 天:RAG 概念、项目初始化、模型客户端", + "第 2 天:加载和切分", + "第 3 天:向量库和幂等入库", + "第 4 天:检索、提示词、带引用的生成", + "第 5 天:FastAPI 接口和流式输出", + "第 6 天:命令行、接入真实模型、人工试验", + "第 7 天:整理、README、复盘", + "本周自查清单" + ] + }, + { + "id": "plan.week06", + "title": "第 6 周:RAG 知识库问答(下)——评测、混合检索、重排、记忆、缓存、LangChain、部署", + "type": "week", + "domain": "plan", + "stack": [ + "postgresql", + "redis", + "docker", + "rag", + "vector-db", + "langchain" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 6 + ], + "order": 6, + "path": "plan/week06-rag-2.md", + "sections": [ + "第 1 天:评测集和指标", + "第 2 天:BM25 关键词检索 + RRF 混合检索", + "第 3 天:重排(Rerank)", + "第 4 天:多轮追问——问题改写 + 会话短期记忆(Redis)", + "第 5 天:缓存、配置组装、多轮对话接口", + "第 6 天:LangChain 对照实现 + Milvus / pgvector", + "第 7 天:Docker Compose 部署 + 复盘", + "本周自查清单" + ] + }, + { + "id": "plan.week07", + "title": "第 7 周:前端工程化查漏补缺 + 两个项目的界面", + "type": "week", + "domain": "plan", + "stack": [ + "nginx", + "cicd", + "vue", + "react", + "typescript", + "vite", + "webpack", + "ssr", + "fe-testing-perf" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 7 + ], + "order": 7, + "path": "plan/week07-frontend.md", + "sections": [ + "本周最终目录", + "第 1 天:pnpm monorepo、TS 严格配置、ESLint + Prettier、共享请求封装", + "第 2 天:SSE 流式解析(fetch + ReadableStream)", + "第 3 天:Vue 3 应用——项目一的任务看板", + "第 4 天:React 应用——项目二的知识库问答界面", + "第 5 天:构建工具和性能优化", + "第 6 天:SSR 基础(Nuxt / Next.js)", + "第 7 天:前端 CI、构建产物部署、复盘", + "本周自查清单(对照招聘“熟悉 Vue / React”的延伸要求)" + ] + }, + { + "id": "plan.week08", + "title": "第 8 周:阶段 0 盘点 + 阶段 1 读通与画图", + "type": "week", + "domain": "plan", + "stack": [ + "git" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 8 + ], + "order": 8, + "path": "plan/week08-inventory-architecture.md", + "sections": [ + "第 1 天:阶段 0——盘点", + "第 2 天:脱敏机制——提交前自动检查", + "第 3 天:阶段 1——怎么读一个大项目", + "第 4 天:画架构图,标出断点", + "第 5 天:接口职责表", + "第 6 天:把流程画成状态机,并用代码验证思路", + "第 7 天:阶段 1 验收 + 口述初稿", + "本周自查清单" + ] + }, + { + "id": "plan.week09", + "title": "第 9 周:阶段 2——五个重点 A~E 深挖 + 案例卡", + "type": "week", + "domain": "plan", + "stack": [], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 9 + ], + "order": 9, + "path": "plan/week09-case-cards.md", + "sections": [ + "第 1 天:A 多 Agent 编排", + "第 2 天:C 流式与长任务", + "第 3 天:B 状态与权威源", + "第 4 天:D 人机协作", + "第 5 天:E 与业务系统集成", + "第 6 天:补写和打磨案例卡", + "第 7 天:汇总设计输入", + "本周自查清单" + ] + }, + { + "id": "plan.week10", + "title": "第 10 周:项目三 M1——手写工具调用循环 + 手写多 Agent 循环 + MCP 服务", + "type": "week", + "domain": "plan", + "stack": [ + "mcp", + "function-calling" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 10 + ], + "order": 10, + "path": "plan/week10-agent-m1-tools-mcp.md", + "sections": [ + "项目三总览", + "第 1 天:初始化 + 支持工具调用的最小模型客户端", + "第 2 天:手写工具调用循环", + "第 3 天:手写多 Agent 循环", + "第 4 天:MCP 概念 + 写一个 MCP 服务", + "第 5 天:在 Cursor 和自己的 Agent 里用 MCP", + "第 6 天:真实模型试跑 + 对照文档(上半)", + "第 7 天:M1 验收" + ] + }, + { + "id": "plan.week11", + "title": "第 11 周:项目三 M2——用 LangGraph 实现多 Agent 编排", + "type": "week", + "domain": "plan", + "stack": [ + "langchain", + "langgraph", + "mcp", + "prompt-engineering" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 11 + ], + "order": 11, + "path": "plan/week11-agent-m2-langgraph.md", + "sections": [ + "第 1 天:LangGraph 基础", + "第 2 天:State、结构化决定、路由规则", + "第 3 天:模型、工具、提示词、节点", + "第 4 天:组装图 + 测试", + "第 5 天:MCP 工具接入 LangGraph + 命令行", + "第 6 天:真实模型试跑和调提示词", + "第 7 天:对照文档 + M2 验收" + ] + }, + { + "id": "plan.week12", + "title": "第 12 周:项目三 M3——检查点续跑、人机协作、后台作业、SSE、长期记忆", + "type": "week", + "domain": "plan", + "stack": [ + "asyncio", + "fastapi", + "langgraph", + "agent-ops" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 12 + ], + "order": 12, + "path": "plan/week12-agent-m3-persistence.md", + "sections": [ + "核心设计:两层状态", + "第 1 天:检查点和续跑", + "第 2 天:长期记忆(Store)", + "第 3 天:业务表和租约", + "第 4 天:后台运行器(RunManager)和报告", + "第 5 天:FastAPI 接口和 SSE", + "第 6 天:页面 + 崩溃恢复演示", + "第 7 天:走查 + M3 验收" + ] + }, + { + "id": "plan.week13", + "title": "第 13 周:项目三 M4——评测集、可观测性、文档、Docker + Dify / Coze 体验", + "type": "week", + "domain": "plan", + "stack": [ + "docker", + "prompt-engineering", + "agent-ops", + "lowcode" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 13 + ], + "order": 13, + "path": "plan/week13-agent-m4-eval-lowcode.md", + "sections": [ + "第 1 天:评测集和规则检查", + "第 2 天:评测脚本、回归测试、用评测驱动改进", + "第 3 天:可观测性(回调、LangSmith / Langfuse)", + "第 4 天:文档(架构、设计取舍、映射表)", + "第 5 天:README、Docker、从零验证、讲解稿", + "第 6~7 天:Dify / Coze 体验(低代码平台)" + ] + }, + { + "id": "plan.week14", + "title": "第 14 周:后端补强——消息队列、gRPC、Redis / MySQL 专题、全部项目部署、CI/CD", + "type": "week", + "domain": "plan", + "stack": [ + "go", + "mysql", + "redis", + "mq", + "grpc-microservices", + "docker", + "nginx", + "linux", + "cicd" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 14 + ], + "order": 14, + "path": "plan/week14-backend-extend-deploy.md", + "sections": [ + "本周最终目录", + "第 1 天:消息队列——RabbitMQ 动手 + Kafka 概念", + "第 2 天:微服务概念 + gRPC", + "第 3 天:Redis 面试专题——锁、缓存三大问题、限流", + "第 4 天:MySQL 面试专题——索引、EXPLAIN、事务和隔离级别", + "第 5 天:把三个项目部署到一台服务器", + "第 6 天:CI/CD——测试、构建镜像、自动部署", + "第 7 天(可选):用 Go 写一个鉴权网关", + "本周验收" + ] + }, + { + "id": "plan.week15", + "title": "第 15 周:阶段 4(上)——作品集、简历、STAR 经历、口述稿", + "type": "week", + "domain": "plan", + "stack": [ + "git" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 15 + ], + "order": 15, + "path": "plan/week15-package-resume.md", + "sections": [ + "本周最终目录", + "第 1 天:整理作品集(3 个公开仓库)", + "第 2 天:简历结构、学历和技能栏", + "第 3 天:项目经历怎么写", + "第 4 天:工作经历——3 条 STAR", + "第 5 天:针对岗位调整简历(关键词对照)", + "第 6 天:口述稿和演示视频", + "第 7 天:自查、请人审阅、阶段 4(上)验收" + ] + }, + { + "id": "plan.week16", + "title": "第 16 周:阶段 4(下)——面试准备、终点验收、投递", + "type": "week", + "domain": "plan", + "stack": [], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": 12, + "week": [ + 16 + ], + "order": 16, + "path": "plan/week16-interview.md", + "sections": [ + "本周最终目录", + "第 1 天:面试笔记(上)——Python 和 FastAPI", + "第 2 天:面试笔记(中)——RAG 和 Agent", + "第 3 天:面试笔记(下)——后端、前端、Go", + "第 4 天:项目深挖和系统设计", + "第 5 天:模拟面试和抽题练习", + "第 6 天:终点验收", + "第 7 天:开始投递,建立复盘循环" + ] + }, + { + "id": "python.asyncio.index", + "title": "asyncio 异步编程", + "type": "index", + "domain": "python", + "stack": [ + "asyncio" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 4, + 5, + 12 + ], + "order": null, + "path": "topics/python/asyncio/index.md", + "sections": [] + }, + { + "id": "python.fastapi.index", + "title": "FastAPI", + "type": "index", + "domain": "python", + "stack": [ + "fastapi" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 4, + 5, + 12 + ], + "order": null, + "path": "topics/python/fastapi/index.md", + "sections": [] + }, + { + "id": "python.python.index", + "title": "Python 语言", + "type": "index", + "domain": "python", + "stack": [ + "python" + ], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [ + 4 + ], + "order": null, + "path": "topics/python/python/index.md", + "sections": [] + }, + { + "id": "scenarios.index", + "title": "跨技术栈企业服务场景", + "type": "index", + "domain": "cross", + "stack": [], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [], + "order": null, + "path": "scenarios/index.md", + "sections": [] + }, + { + "id": "topics.index", + "title": "专项学习总目录", + "type": "index", + "domain": "plan", + "stack": [], + "tags": [], + "level": null, + "prerequisites": [], + "related": [], + "est_hours": null, + "week": [], + "order": null, + "path": "topics/index.md", + "sections": [ + "后端(`backend`)", + "运维与工程(`devops`)", + "Python(`python`)", + "AI 应用(`ai`)", + "前端(`frontend`)" + ] + } + ] +} diff --git a/plan/README.md b/plan/README.md index 2a6df74..0209658 100644 --- a/plan/README.md +++ b/plan/README.md @@ -1,3 +1,11 @@ +--- +id: plan.index +title: 转岗计划总纲 +type: index +domain: plan +stack: [] +--- + # 转岗计划总纲:Python AI 应用 / Agent 开发为主,Go 全栈为辅(16 周) 这是整个计划的入口文件。换了电脑或者隔一段时间回来,先看第 13 节“进度记录”,再打开当前所在周的计划文件继续做。 @@ -314,15 +322,20 @@ ```text zhuangang/ ├── .gitignore # 至少包含 notes/private/、.env、*.db、data/、node_modules/、.venv/ -├── README.md -├── plan/ # 本计划(见下面的文件清单) +├── README.md # 仓库入口 +├── CONTRIBUTING.md # 内容规范(目录、frontmatter、各类型写法) +├── catalog.json # 内容目录(tools/build_catalog.py 生成) +├── schema/ # frontmatter 的 JSON Schema +├── tools/ # build_catalog.py、run_examples.py、check_sensitive.py +├── plan/ # 本计划:总纲 + 16 个周文件(见下面的文件清单) +├── topics/ # 专项学习:<领域>/<技术栈>/ 课程、场景、面试题、示例 +├── scenarios/ # 跨技术栈的企业服务场景 ├── go-learning/ # 第 1 周:Go 语法练习 ├── todo-api/ # 第 1~2 周:Gin 接口 + PostgreSQL + JWT ├── task-board/ # 第 3 周:项目一后端 ├── py-learning/ # 第 4 周:Python 练习 + FastAPI ├── rag-qa/ # 第 5~6 周:项目二 ├── web/ # 第 7 周:pnpm monorepo(shared、board-vue、rag-react) -├── tools/ # 第 8 周:check_sensitive.py(提交前脱敏检查) ├── notes/ # 第 8~9 周:盘点、架构图、案例卡(脱敏);低代码体验笔记 │ ├── cards/ │ └── private/ # 不进仓库 @@ -333,6 +346,8 @@ zhuangang/ └── career/ # 第 15~16 周:简历、口述稿、面试笔记 ``` +**周计划和专题的关系**:周文件是“日程”——每天做什么、建哪些文件、怎么验收;概念讲解、企业场景和面试题在 `topics/` 和 `scenarios/` 里,周文件开头的“本周相关专题”列出了链接。单独补某个技术栈时直接从 [topics/index.md](../topics/index.md) 进入。 + ### 计划文件清单(`plan/`) | 文件 | 内容 | diff --git a/plan/week01-go-gin.md b/plan/week01-go-gin.md index 6a1a9a6..1093b29 100644 --- a/plan/week01-go-gin.md +++ b/plan/week01-go-gin.md @@ -1,3 +1,14 @@ +--- +id: plan.week01 +title: "第 1 周:Go 基础 + Gin 写 REST 接口" +type: week +domain: plan +stack: [go, gin, git] +week: [1] +est_hours: 12 +order: 1 +--- + # 第 1 周:Go 基础 + Gin 写 REST 接口 > 第一段“Go 全栈基础”(第 1~3 周)的第 1 周。总纲见 `README.md`,下周 `week02-db-auth.md`。 diff --git a/plan/week02-db-auth.md b/plan/week02-db-auth.md index e347e9b..7e72bf1 100644 --- a/plan/week02-db-auth.md +++ b/plan/week02-db-auth.md @@ -1,3 +1,14 @@ +--- +id: plan.week02 +title: "第 2 周:数据库(PostgreSQL 为主,兼顾 MySQL)+ 注册登录与 JWT" +type: week +domain: plan +stack: [go, gin, postgresql, mysql] +week: [2] +est_hours: 12 +order: 2 +--- + # 第 2 周:数据库(PostgreSQL 为主,兼顾 MySQL)+ 注册登录与 JWT > 第一段“Go 全栈基础”的第 2 周。上周 `week01-go-gin.md`,下周 `week03-project1.md`。 diff --git a/plan/week03-project1.md b/plan/week03-project1.md index d201cb6..ffe660e 100644 --- a/plan/week03-project1.md +++ b/plan/week03-project1.md @@ -1,3 +1,14 @@ +--- +id: plan.week03 +title: "第 3 周:项目一“团队任务看板”:权限 + Redis + 消息队列 + Docker 部署" +type: week +domain: plan +stack: [go, gin, postgresql, redis, mq, docker, nginx, cicd] +week: [3] +est_hours: 12 +order: 3 +--- + # 第 3 周:项目一“团队任务看板”:权限 + Redis + 消息队列 + Docker 部署 > 第一段“Go 全栈基础”的最后一周。上周 `week02-db-auth.md`,下周 `week04-python.md`。 diff --git a/plan/week04-python.md b/plan/week04-python.md index 8617cfe..ccde268 100644 --- a/plan/week04-python.md +++ b/plan/week04-python.md @@ -1,3 +1,14 @@ +--- +id: plan.week04 +title: "第 4 周:Python 速成(给 JS 开发者)+ FastAPI 基础" +type: week +domain: plan +stack: [python, asyncio, fastapi] +week: [4] +est_hours: 12 +order: 4 +--- + # 第 4 周:Python 速成(给 JS 开发者)+ FastAPI 基础 > 第二段“Python 与 AI 应用”的第 1 周。从这周起 **Python 是求职主语言**。上周 `week03-project1.md`,下周 `week05-rag-1.md`。 diff --git a/plan/week05-rag-1.md b/plan/week05-rag-1.md index 47716ea..624b966 100644 --- a/plan/week05-rag-1.md +++ b/plan/week05-rag-1.md @@ -1,3 +1,14 @@ +--- +id: plan.week05 +title: "第 5 周:RAG 知识库问答(上)——手写主流程" +type: week +domain: plan +stack: [asyncio, fastapi, rag, vector-db, prompt-engineering] +week: [5] +est_hours: 12 +order: 5 +--- + # 第 5 周:RAG 知识库问答(上)——手写主流程 > 第二段“Python 与 AI 应用”的第 2 周,也是**项目二 `rag-qa`** 的第 1 周。上周 `week04-python.md`,下周 `week06-rag-2.md`(评测、混合检索、重排、缓存、LangChain 对照、部署)。前端界面放到第 7 周统一做。 diff --git a/plan/week06-rag-2.md b/plan/week06-rag-2.md index 5676a88..077645b 100644 --- a/plan/week06-rag-2.md +++ b/plan/week06-rag-2.md @@ -1,3 +1,14 @@ +--- +id: plan.week06 +title: "第 6 周:RAG 知识库问答(下)——评测、混合检索、重排、记忆、缓存、LangChain、部署" +type: week +domain: plan +stack: [postgresql, redis, docker, rag, vector-db, langchain] +week: [6] +est_hours: 12 +order: 6 +--- + # 第 6 周:RAG 知识库问答(下)——评测、混合检索、重排、记忆、缓存、LangChain、部署 > 项目二 `rag-qa` 的第 2 周。上周 `week05-rag-1.md` 完成了手写主流程;下周 `week07-frontend.md` 做前端界面。 diff --git a/plan/week07-frontend.md b/plan/week07-frontend.md index 891849b..148c18c 100644 --- a/plan/week07-frontend.md +++ b/plan/week07-frontend.md @@ -1,3 +1,14 @@ +--- +id: plan.week07 +title: "第 7 周:前端工程化查漏补缺 + 两个项目的界面" +type: week +domain: plan +stack: [nginx, cicd, vue, react, typescript, vite, webpack, ssr, fe-testing-perf] +week: [7] +est_hours: 12 +order: 7 +--- + # 第 7 周:前端工程化查漏补缺 + 两个项目的界面 > 第二段的第 4 周。上周 `week06-rag-2.md`,下周 `week08-inventory-architecture.md`。 diff --git a/plan/week08-inventory-architecture.md b/plan/week08-inventory-architecture.md index 1590010..d14e682 100644 --- a/plan/week08-inventory-architecture.md +++ b/plan/week08-inventory-architecture.md @@ -1,3 +1,14 @@ +--- +id: plan.week08 +title: "第 8 周:阶段 0 盘点 + 阶段 1 读通与画图" +type: week +domain: plan +stack: [git] +week: [8] +est_hours: 12 +order: 8 +--- + # 第 8 周:阶段 0 盘点 + 阶段 1 读通与画图 > 第三段“Agent 主线”的第 1 周。上周 `week07-frontend.md`,下周 `week09-case-cards.md`。 diff --git a/plan/week09-case-cards.md b/plan/week09-case-cards.md index cf4dc19..21457da 100644 --- a/plan/week09-case-cards.md +++ b/plan/week09-case-cards.md @@ -1,3 +1,14 @@ +--- +id: plan.week09 +title: "第 9 周:阶段 2——五个重点 A~E 深挖 + 案例卡" +type: week +domain: plan +stack: [] +week: [9] +est_hours: 12 +order: 9 +--- + # 第 9 周:阶段 2——五个重点 A~E 深挖 + 案例卡 > 第三段的第 2 周。上周 `week08-inventory-architecture.md`,下周 `week10-agent-m1-tools-mcp.md`。 diff --git a/plan/week10-agent-m1-tools-mcp.md b/plan/week10-agent-m1-tools-mcp.md index b1fb680..4e23831 100644 --- a/plan/week10-agent-m1-tools-mcp.md +++ b/plan/week10-agent-m1-tools-mcp.md @@ -1,3 +1,14 @@ +--- +id: plan.week10 +title: "第 10 周:项目三 M1——手写工具调用循环 + 手写多 Agent 循环 + MCP 服务" +type: week +domain: plan +stack: [mcp, function-calling] +week: [10] +est_hours: 12 +order: 10 +--- + # 第 10 周:项目三 M1——手写工具调用循环 + 手写多 Agent 循环 + MCP 服务 > 第三段的第 3 周,**项目三 `agent-mini`(阶段 3 主交付)** 的第 1 周。上周 `week09-case-cards.md`,下周 `week11-agent-m2-langgraph.md`。 diff --git a/plan/week11-agent-m2-langgraph.md b/plan/week11-agent-m2-langgraph.md index 274695d..2cf5e08 100644 --- a/plan/week11-agent-m2-langgraph.md +++ b/plan/week11-agent-m2-langgraph.md @@ -1,3 +1,14 @@ +--- +id: plan.week11 +title: "第 11 周:项目三 M2——用 LangGraph 实现多 Agent 编排" +type: week +domain: plan +stack: [langchain, langgraph, mcp, prompt-engineering] +week: [11] +est_hours: 12 +order: 11 +--- + # 第 11 周:项目三 M2——用 LangGraph 实现多 Agent 编排 > 项目三的第 2 周。上周 `week10-agent-m1-tools-mcp.md`(手写版 + MCP),下周 `week12-agent-m3-persistence.md`(续跑、中断、后台作业、SSE、记忆)。 diff --git a/plan/week12-agent-m3-persistence.md b/plan/week12-agent-m3-persistence.md index a74aac4..c757db8 100644 --- a/plan/week12-agent-m3-persistence.md +++ b/plan/week12-agent-m3-persistence.md @@ -1,3 +1,14 @@ +--- +id: plan.week12 +title: "第 12 周:项目三 M3——检查点续跑、人机协作、后台作业、SSE、长期记忆" +type: week +domain: plan +stack: [asyncio, fastapi, langgraph, agent-ops] +week: [12] +est_hours: 12 +order: 12 +--- + # 第 12 周:项目三 M3——检查点续跑、人机协作、后台作业、SSE、长期记忆 > 项目三的第 3 周,**整个计划最核心的一周**:第 9 周案例卡里“若重做的设计”在这里落地。上周 `week11-agent-m2-langgraph.md`,下周 `week13-agent-m4-eval-lowcode.md`。 diff --git a/plan/week13-agent-m4-eval-lowcode.md b/plan/week13-agent-m4-eval-lowcode.md index 499d568..5b6ab13 100644 --- a/plan/week13-agent-m4-eval-lowcode.md +++ b/plan/week13-agent-m4-eval-lowcode.md @@ -1,3 +1,14 @@ +--- +id: plan.week13 +title: "第 13 周:项目三 M4——评测集、可观测性、文档、Docker + Dify / Coze 体验" +type: week +domain: plan +stack: [docker, prompt-engineering, agent-ops, lowcode] +week: [13] +est_hours: 12 +order: 13 +--- + # 第 13 周:项目三 M4——评测集、可观测性、文档、Docker + Dify / Coze 体验 > 项目三的最后一周(阶段 3 出门)。上周 `week12-agent-m3-persistence.md`,下周 `week14-backend-extend-deploy.md`。 diff --git a/plan/week14-backend-extend-deploy.md b/plan/week14-backend-extend-deploy.md index bd8bd59..5e47f57 100644 --- a/plan/week14-backend-extend-deploy.md +++ b/plan/week14-backend-extend-deploy.md @@ -1,3 +1,14 @@ +--- +id: plan.week14 +title: "第 14 周:后端补强——消息队列、gRPC、Redis / MySQL 专题、全部项目部署、CI/CD" +type: week +domain: plan +stack: [go, mysql, redis, mq, grpc-microservices, docker, nginx, linux, cicd] +week: [14] +est_hours: 12 +order: 14 +--- + # 第 14 周:后端补强——消息队列、gRPC、Redis / MySQL 专题、全部项目部署、CI/CD > 第四段的第 1 周。上周 `week13-agent-m4-eval-lowcode.md`,下周 `week15-package-resume.md`。 diff --git a/plan/week15-package-resume.md b/plan/week15-package-resume.md index 6dec3d4..245959f 100644 --- a/plan/week15-package-resume.md +++ b/plan/week15-package-resume.md @@ -1,3 +1,14 @@ +--- +id: plan.week15 +title: "第 15 周:阶段 4(上)——作品集、简历、STAR 经历、口述稿" +type: week +domain: plan +stack: [git] +week: [15] +est_hours: 12 +order: 15 +--- + # 第 15 周:阶段 4(上)——作品集、简历、STAR 经历、口述稿 > 第四段的第 2 周。上周 `week14-backend-extend-deploy.md`,下周 `week16-interview.md`。 diff --git a/plan/week16-interview.md b/plan/week16-interview.md index 10f02c1..925bce0 100644 --- a/plan/week16-interview.md +++ b/plan/week16-interview.md @@ -1,3 +1,14 @@ +--- +id: plan.week16 +title: "第 16 周:阶段 4(下)——面试准备、终点验收、投递" +type: week +domain: plan +stack: [] +week: [16] +est_hours: 12 +order: 16 +--- + # 第 16 周:阶段 4(下)——面试准备、终点验收、投递 > 整个计划的最后一周。上周 `week15-package-resume.md`。总纲见 `README.md` 第 14 节“终点验收清单”。 diff --git a/scenarios/index.md b/scenarios/index.md new file mode 100644 index 0000000..ad0264e --- /dev/null +++ b/scenarios/index.md @@ -0,0 +1,22 @@ +--- +id: scenarios.index +title: 跨技术栈企业服务场景 +type: index +domain: cross +stack: [] +--- + +# 跨技术栈企业服务场景 + +每个场景按“业务背景与问题 → 约束 → 方案设计 → 关键代码 → 取舍 → 易错点 → 面试怎么讲”组织,综合多个技术栈。 + +> 建设中,计划包含: + +- 客服知识库问答(`customer-service-kb`) +- 工单系统(智能分类与流转)(`ticket-system`) +- 审批流 + 人工介入的 Agent(`approval-human-in-loop`) +- 报表生成 Agent(自然语言查数)(`report-agent`) +- 秒杀 / 高并发抢购(`flash-sale`) +- 多租户 SaaS(`multi-tenant-saas`) +- 内容审核(`content-moderation`) +- 数据同步(数据库到搜索 / 向量库)(`data-sync`) diff --git a/schema/frontmatter.schema.json b/schema/frontmatter.schema.json new file mode 100644 index 0000000..51be866 --- /dev/null +++ b/schema/frontmatter.schema.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "zhuangang/frontmatter.schema.json", + "title": "zhuangang 内容文件的 frontmatter", + "description": "plan/、topics/、scenarios/ 下每个 .md 文件开头的 YAML frontmatter。说明见 CONTRIBUTING.md。", + "type": "object", + "required": ["id", "title", "type", "domain"], + "properties": { + "id": {"type": "string", "pattern": "^[a-z0-9]+(\\.[a-z0-9-]+)+$", "description": "全局唯一、稳定不变的内容 ID"}, + "title": {"type": "string"}, + "type": {"enum": ["index", "lesson", "scenario", "interview", "project", "week"]}, + "domain": {"enum": ["backend", "devops", "python", "ai", "frontend", "cross", "plan"]}, + "stack": {"type": "array", "items": {"type": "string"}, "description": "技术栈标识,与 topics/// 目录名一致"}, + "tags": {"type": "array", "items": {"type": "string"}}, + "level": {"enum": ["basic", "intermediate", "advanced"]}, + "prerequisites": {"type": "array", "items": {"type": "string"}, "description": "先修内容的 id"}, + "related": {"type": "array", "items": {"type": "string"}, "description": "相关内容的 id"}, + "est_hours": {"type": "number", "minimum": 0}, + "week": {"type": "array", "items": {"type": "integer", "minimum": 1, "maximum": 16}, "description": "在 16 周计划中的哪几周用到"}, + "order": {"type": "integer", "description": "同一技术栈内的排序"} + }, + "allOf": [ + {"if": {"properties": {"type": {"enum": ["lesson", "scenario", "interview"]}}}, "then": {"required": ["level", "stack"]}} + ] +} diff --git a/tools/build_catalog.py b/tools/build_catalog.py new file mode 100644 index 0000000..98df416 --- /dev/null +++ b/tools/build_catalog.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python3 +"""内容校验 + 目录生成(只用标准库,Python 3.10+)。 + +用法: + python3 tools/build_catalog.py # 校验并写出 catalog.json + python3 tools/build_catalog.py --check # 只校验,不写文件(CI / 提交前用) + python3 tools/build_catalog.py --strict # 额外要求:每个技术栈至少 1 课、1 个场景、1 份面试题 + +校验内容:frontmatter 字段和取值、id 唯一、prerequisites / related 指向存在的 id、 +相对链接指向存在的文件、代码块围栏闭合、各类型必需的小节标题。规范见 CONTRIBUTING.md。 +""" +from __future__ import annotations + +import json +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +CONTENT_DIRS = ["plan", "topics", "scenarios"] +SCHEMA_VERSION = 1 + +TYPES = {"index", "lesson", "scenario", "interview", "project", "week"} +DOMAINS = {"backend", "devops", "python", "ai", "frontend", "cross", "plan"} +LEVELS = {"basic", "intermediate", "advanced"} +QUESTION_LEVELS = ["基础", "进阶", "场景题"] +ID_RE = re.compile(r"^[a-z0-9]+(?:\.[a-z0-9-]+)+$") +REQUIRED = {"id", "title", "type", "domain"} +LIST_FIELDS = {"stack", "tags", "prerequisites", "related", "week"} +REQUIRED_SECTIONS = { + "lesson": ["解释说明", "案例", "代码示例", "易错点"], + "scenario": ["业务背景", "约束", "方案设计", "关键代码", "取舍", "易错点", "面试怎么讲"], +} +FENCE_RE = re.compile(r"^\s*(```|~~~)") +LINK_RE = re.compile(r"(?= 2: + return v[1:-1] + if re.fullmatch(r"-?\d+", v): + return int(v) + if re.fullmatch(r"-?\d+\.\d+", v): + return float(v) + if v in ("true", "false"): + return v == "true" + return v + + +def parse_frontmatter(text: str) -> tuple[dict | None, str, list[str]]: + """只支持规范里约定的子集:`键: 标量` 和 `键: [a, b]`(单行流式列表)。""" + errs: list[str] = [] + if not text.startswith("---\n"): + return None, text, ["缺少 frontmatter(文件第一行必须是 ---)"] + end = text.find("\n---\n", 4) + if end < 0: + return None, text, ["frontmatter 没有结束的 ---"] + meta: dict = {} + for n, line in enumerate(text[4:end].splitlines(), 2): + if not line.strip() or line.lstrip().startswith("#"): + continue + m = re.match(r"^([a-z_]+):\s*(.*)$", line) + if not m: + errs.append(f"frontmatter 第 {n} 行无法解析:{line!r}") + continue + k, v = m.group(1), m.group(2).strip() + if v.startswith("["): + if not v.endswith("]"): + errs.append(f"frontmatter 字段 {k} 的列表必须写在一行内") + continue + inner = v[1:-1].strip() + meta[k] = [parse_scalar(x) for x in inner.split(",")] if inner else [] + else: + meta[k] = parse_scalar(v) + return meta, text[end + 5:], errs + + +def scan_body(body: str) -> tuple[bool, list[str], list[str], dict[str, int]]: + """返回:围栏是否闭合、二级标题、链接目标、按级别统计的面试题数。""" + in_fence, fence_mark = False, "" + headings, links = [], [] + counts = {k: 0 for k in QUESTION_LEVELS} + for line in body.splitlines(): + m = FENCE_RE.match(line) + if m: + if not in_fence: + in_fence, fence_mark = True, m.group(1) + elif m.group(1) == fence_mark and line.strip() == fence_mark: + in_fence = False + continue + if in_fence: + continue + if line.startswith("## "): + headings.append(line[3:].strip()) + q = QUESTION_RE.match(line) + if q: + counts[q.group(1)] += 1 + links += LINK_RE.findall(line) + return not in_fence, headings, links, counts + + +def main() -> int: + check_only = "--check" in sys.argv + strict = "--strict" in sys.argv + errors: list[str] = [] + items: list[dict] = [] + files = sorted(p for d in CONTENT_DIRS for p in (ROOT / d).rglob("*.md") + if "examples" not in p.relative_to(ROOT).parts and "node_modules" not in p.parts) + for path in files: + rel = path.relative_to(ROOT).as_posix() + text = path.read_text(encoding="utf-8") + meta, body, errs = parse_frontmatter(text) + errors += [f"{rel}: {e}" for e in errs] + if meta is None: + continue + for f in REQUIRED - meta.keys(): + errors.append(f"{rel}: 缺少必填字段 {f}") + for f in LIST_FIELDS & meta.keys(): + if not isinstance(meta[f], list): + errors.append(f"{rel}: 字段 {f} 必须是列表,例如 {f}: [a, b]") + t = meta.get("type") + if t not in TYPES: + errors.append(f"{rel}: type={t!r} 不在 {sorted(TYPES)} 中") + if meta.get("domain") not in DOMAINS: + errors.append(f"{rel}: domain={meta.get('domain')!r} 不在 {sorted(DOMAINS)} 中") + if not ID_RE.match(str(meta.get("id", ""))): + errors.append(f"{rel}: id={meta.get('id')!r} 格式不对(小写字母数字,用 . 分段)") + if t in ("lesson", "scenario", "interview") and meta.get("level") not in LEVELS: + errors.append(f"{rel}: {t} 必须有 level({sorted(LEVELS)})") + if "est_hours" in meta and not isinstance(meta["est_hours"], (int, float)): + errors.append(f"{rel}: est_hours 必须是数字") + for w in meta.get("week", []) if isinstance(meta.get("week"), list) else []: + if not isinstance(w, int) or not 1 <= w <= 16: + errors.append(f"{rel}: week 取值 {w!r} 必须是 1~16 的整数") + closed, headings, links, counts = scan_body(body) + if not closed: + errors.append(f"{rel}: 代码块围栏没有闭合") + for sec in REQUIRED_SECTIONS.get(t, []): + if not any(sec in h for h in headings): + errors.append(f"{rel}: {t} 缺少小节“## {sec}”") + if t == "interview" and sum(counts.values()) == 0: + errors.append(f"{rel}: 面试题文件没有题目(标题格式:### 【基础】问题)") + for target in links: + if re.match(r"^[a-z]+:", target) or target.startswith("#"): + continue + dest = (path.parent / target.split("#", 1)[0]).resolve() + if not dest.exists(): + errors.append(f"{rel}: 链接指向的文件不存在:{target}") + item = { + "id": meta.get("id"), "title": meta.get("title"), "type": t, "domain": meta.get("domain"), + "stack": meta.get("stack", []), "tags": meta.get("tags", []), "level": meta.get("level"), + "prerequisites": meta.get("prerequisites", []), "related": meta.get("related", []), + "est_hours": meta.get("est_hours"), "week": meta.get("week", []), "order": meta.get("order"), + "path": rel, "sections": headings, + } + if t == "interview": + item["questions"] = counts + items.append(item) + + ids = {} + for it in items: + if it["id"] in ids: + errors.append(f"{it['path']}: id {it['id']} 与 {ids[it['id']]} 重复") + ids[it["id"]] = it["path"] + for it in items: + for f in ("prerequisites", "related"): + for ref in it[f] if isinstance(it[f], list) else []: + if ref not in ids: + errors.append(f"{it['path']}: {f} 引用了不存在的 id:{ref}") + + stacks = [] + for it in items: + if it["type"] == "index" and it["path"].startswith("topics/") and it["path"].count("/") == 3: + sid = it["stack"][0] if it["stack"] else None + mine = [x for x in items if x["path"].startswith(it["path"].rsplit("/", 1)[0] + "/")] + q = {k: 0 for k in QUESTION_LEVELS} + for x in mine: + for k, v in x.get("questions", {}).items(): + q[k] += v + stack_dir = ROOT / it["path"].rsplit("/", 1)[0] + examples = sorted(p.relative_to(ROOT).as_posix() for p in (stack_dir / "examples").glob("*")) \ + if (stack_dir / "examples").exists() else [] + entry = {"stack": sid, "domain": it["domain"], "title": it["title"], "index": it["path"], + "lessons": sum(x["type"] == "lesson" for x in mine), + "scenarios": sum(x["type"] == "scenario" for x in mine), + "interview_questions": q, "examples": examples} + stacks.append(entry) + if strict and (entry["lessons"] == 0 or entry["scenarios"] == 0 or sum(q.values()) == 0): + errors.append(f"{it['path']}: 严格模式要求技术栈 {sid} 至少有 1 课、1 个场景和面试题") + stacks.sort(key=lambda s: (s["domain"], s["stack"] or "")) + + if errors: + print(f"校验失败:{len(errors)} 个问题") + for e in errors: + print(" -", e) + return 1 + q_total = {k: sum(s["interview_questions"][k] for s in stacks) for k in QUESTION_LEVELS} + print(f"校验通过:{len(items)} 个文件,{len(stacks)} 个技术栈," + f"{sum(i['type'] == 'lesson' for i in items)} 课,{sum(i['type'] == 'scenario' for i in items)} 个场景," + f"面试题 {sum(q_total.values())} 道({'、'.join(f'{k} {v}' for k, v in q_total.items())})") + if not check_only: + catalog = {"schema_version": SCHEMA_VERSION, "generated_by": "tools/build_catalog.py", + "stacks": stacks, "items": sorted(items, key=lambda x: x["id"])} + (ROOT / "catalog.json").write_text(json.dumps(catalog, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + print("已写出 catalog.json") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/check_sensitive.py b/tools/check_sensitive.py new file mode 100644 index 0000000..629425f --- /dev/null +++ b/tools/check_sensitive.py @@ -0,0 +1,67 @@ +# tools/check_sensitive.py —— 提交前扫描暂存区内容 +# 不自动运行:作为 pre-commit 钩子在仓库根目录执行;加 --self-test 可以单独自检 +import re +import subprocess +import sys +from pathlib import Path + +PATTERNS = { + "内网 IP": re.compile(r"\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b|\b192\.168\.\d{1,3}\.\d{1,3}\b|\b172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}\b"), + "疑似密钥": re.compile(r"(?i)\b(?:sk|ak|api[_-]?key|secret|token)[\w-]*\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{16,}"), + "私钥": re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----"), + "root 绝对路径": re.compile(r"(? list[str]: + if not WORDS_FILE.exists(): + return [] + return [w.strip() for w in WORDS_FILE.read_text(encoding="utf-8").splitlines() if w.strip() and not w.startswith("#")] + + +def scan_text(name: str, text: str, words: list[str]) -> list[str]: + problems = [] + for no, line in enumerate(text.splitlines(), start=1): + if ALLOW_MARK in line: + continue + for label, pat in PATTERNS.items(): + if pat.search(line): + problems.append(f"{name}:{no} {label}") + for w in words: + if w.lower() in line.lower(): + problems.append(f"{name}:{no} 敏感词(见私有清单)") # 不打印敏感词本身 + return problems + + +def staged_files() -> list[str]: + out = subprocess.run(["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"], + capture_output=True, text=True, check=True).stdout + return [f for f in out.splitlines() if f] + + +def main() -> int: + words = load_words() + problems = [] + for f in staged_files(): + content = subprocess.run(["git", "show", f":{f}"], capture_output=True).stdout # 读暂存区版本 + try: + problems += scan_text(f, content.decode("utf-8"), words) + except UnicodeDecodeError: + continue # 跳过二进制文件 + for p in problems: + print("✗", p) + if problems: + print("发现疑似敏感内容,已阻止提交。确认无误的行可加注释 sensitive-ok。") + return 1 if problems else 0 + + +if __name__ == "__main__" and "--self-test" in sys.argv: + sample = "url: http://192.168.1.20:8080\napi_key = 'abcdefghijklmnopqrstuvwxyz'\n正常的一行\n" # sensitive-ok + found = scan_text("demo.md", sample, ["某客户"]) + assert len(found) == 2, found + assert scan_text("demo.md", "某客户的需求", ["某客户"]) == ["demo.md:1 敏感词(见私有清单)"] + print("自检通过:", found) +elif __name__ == "__main__": + sys.exit(main()) diff --git a/tools/run_examples.py b/tools/run_examples.py new file mode 100644 index 0000000..23aa20c --- /dev/null +++ b/tools/run_examples.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +"""运行 topics/**/examples/ 下的示例代码(抽查“代码能跑”)。 + +- Go:含 go.mod 的目录执行 `go vet ./... && go test ./...` +- Python:*.py 直接运行(文件开头可写 `# requires: 包1, 包2`,缺包时跳过);test_*.py 用 pytest 运行 +- TypeScript:*.ts 用 Node.js 直接运行(需要 Node 23.6+ 的类型剥离,推荐 Node 24 LTS) +- 文件开头写 `# 不自动运行` / `// 不自动运行` 的跳过(需要外部服务的示例) + +用法:python3 tools/run_examples.py [路径过滤关键词] +""" +from __future__ import annotations + +import importlib.util +import os +import re +import shutil +import subprocess +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +def run(cmd: list[str] | str, cwd: Path, timeout: int = 180) -> tuple[bool, str]: + try: + p = subprocess.run(cmd, cwd=cwd, shell=isinstance(cmd, str), capture_output=True, text=True, timeout=timeout, + env={**os.environ, "PYTHONPATH": str(cwd)}) + return p.returncode == 0, (p.stdout + p.stderr)[-1500:] + except subprocess.TimeoutExpired: + return False, "超时" + + +def node_ok() -> bool: + if not shutil.which("node"): + return False + v = subprocess.run(["node", "-v"], capture_output=True, text=True).stdout.strip().lstrip("v").split(".") + return (int(v[0]), int(v[1])) >= (23, 6) + + +def main() -> int: + flt = sys.argv[1] if len(sys.argv) > 1 else "" + results: list[tuple[str, str, str]] = [] + has_node = node_ok() + for ex in sorted(ROOT.glob("topics/**/examples/*")): + rel = ex.relative_to(ROOT).as_posix() + if flt and flt not in rel: + continue + if ex.is_dir() and (ex / "go.mod").exists(): + if not shutil.which("go"): + results.append(("SKIP", rel, "没有安装 Go")) + continue + ok, out = run("go vet ./... && go test ./...", ex) + results.append(("PASS" if ok else "FAIL", rel, "" if ok else out)) + continue + targets = [ex] if ex.is_file() else sorted(ex.rglob("*")) + for f in targets: + frel = f.relative_to(ROOT).as_posix() + if f.suffix not in (".py", ".ts") or "node_modules" in f.parts: + continue + head = f.read_text(encoding="utf-8")[:400] + if "不自动运行" in head: + results.append(("SKIP", frel, "标记为不自动运行")) + continue + if f.suffix == ".py": + m = re.search(r"^# requires:\s*(.+)$", head, re.M) + missing = [p.strip() for p in m.group(1).split(",")] if m else [] + missing = [p for p in missing if importlib.util.find_spec(p) is None] + if missing: + results.append(("SKIP", frel, f"缺少依赖 {missing}")) + continue + cmd = [sys.executable, "-m", "pytest", "-q", f.name] if f.name.startswith("test_") \ + else [sys.executable, f.name] + ok, out = run(cmd, f.parent) + else: + if not has_node: + results.append(("SKIP", frel, "需要 Node 23.6+")) + continue + ok, out = run(["node", f.name], f.parent) + results.append(("PASS" if ok else "FAIL", frel, "" if ok else out)) + for status, rel, out in results: + print(f"{status:4} {rel}" + (f"\n{out}" if out and status == "FAIL" else f" ({out})" if out else "")) + n = {s: sum(r[0] == s for r in results) for s in ("PASS", "FAIL", "SKIP")} + print(f"\n通过 {n['PASS']},失败 {n['FAIL']},跳过 {n['SKIP']}") + return 1 if n["FAIL"] else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/topics/ai/agent-ops/index.md b/topics/ai/agent-ops/index.md new file mode 100644 index 0000000..da5044e --- /dev/null +++ b/topics/ai/agent-ops/index.md @@ -0,0 +1,15 @@ +--- +id: ai.agent-ops.index +title: Agent 记忆、评测与可观测性 +type: index +domain: ai +stack: [agent-ops] +tags: [] +week: [12, 13] +--- + +# Agent 记忆、评测与可观测性 + +短期 / 长期记忆、评测集、LLM 评分、追踪、成本。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/function-calling/index.md b/topics/ai/function-calling/index.md new file mode 100644 index 0000000..0a12620 --- /dev/null +++ b/topics/ai/function-calling/index.md @@ -0,0 +1,15 @@ +--- +id: ai.function-calling.index +title: Function Calling 工具调用 +type: index +domain: ai +stack: [function-calling] +tags: [] +week: [10] +--- + +# Function Calling 工具调用 + +工具定义、调用循环、参数校验、安全。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/langchain/index.md b/topics/ai/langchain/index.md new file mode 100644 index 0000000..39b0e1a --- /dev/null +++ b/topics/ai/langchain/index.md @@ -0,0 +1,15 @@ +--- +id: ai.langchain.index +title: LangChain +type: index +domain: ai +stack: [langchain] +tags: [] +week: [6, 11] +--- + +# LangChain + +模型与消息、LCEL、工具、结构化输出。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/langgraph/index.md b/topics/ai/langgraph/index.md new file mode 100644 index 0000000..275f075 --- /dev/null +++ b/topics/ai/langgraph/index.md @@ -0,0 +1,15 @@ +--- +id: ai.langgraph.index +title: LangGraph +type: index +domain: ai +stack: [langgraph] +tags: [] +week: [11, 12] +--- + +# LangGraph + +状态图、条件路由、检查点续跑、interrupt、长期记忆。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/lowcode/index.md b/topics/ai/lowcode/index.md new file mode 100644 index 0000000..27318bf --- /dev/null +++ b/topics/ai/lowcode/index.md @@ -0,0 +1,15 @@ +--- +id: ai.lowcode.index +title: Dify / Coze 低代码平台 +type: index +domain: ai +stack: [lowcode] +tags: [] +week: [13] +--- + +# Dify / Coze 低代码平台 + +知识库、工作流、插件,和写代码的取舍。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/mcp/index.md b/topics/ai/mcp/index.md new file mode 100644 index 0000000..5d24de0 --- /dev/null +++ b/topics/ai/mcp/index.md @@ -0,0 +1,15 @@ +--- +id: ai.mcp.index +title: MCP 模型上下文协议 +type: index +domain: ai +stack: [mcp] +tags: [] +week: [10, 11] +--- + +# MCP 模型上下文协议 + +协议概念、tools / resources / prompts、服务端与客户端。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/prompt-engineering/index.md b/topics/ai/prompt-engineering/index.md new file mode 100644 index 0000000..0e8377a --- /dev/null +++ b/topics/ai/prompt-engineering/index.md @@ -0,0 +1,15 @@ +--- +id: ai.prompt-engineering.index +title: 提示词与上下文工程 +type: index +domain: ai +stack: [prompt-engineering] +tags: [] +week: [5, 11, 13] +--- + +# 提示词与上下文工程 + +提示词结构、结构化输出、上下文工程、提示词注入防护。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/rag/index.md b/topics/ai/rag/index.md new file mode 100644 index 0000000..0731a50 --- /dev/null +++ b/topics/ai/rag/index.md @@ -0,0 +1,15 @@ +--- +id: ai.rag.index +title: RAG 检索增强生成 +type: index +domain: ai +stack: [rag] +tags: [] +week: [5, 6] +--- + +# RAG 检索增强生成 + +加载切分、嵌入、检索、混合检索与重排、引用与拒答、评测。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/ai/vector-db/index.md b/topics/ai/vector-db/index.md new file mode 100644 index 0000000..1c87a4c --- /dev/null +++ b/topics/ai/vector-db/index.md @@ -0,0 +1,15 @@ +--- +id: ai.vector-db.index +title: 向量数据库 +type: index +domain: ai +stack: [vector-db] +tags: [] +week: [5, 6] +--- + +# 向量数据库 + +近似最近邻索引、距离度量、Chroma / Milvus / pgvector 选型。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/gin/index.md b/topics/backend/gin/index.md new file mode 100644 index 0000000..a3f26d2 --- /dev/null +++ b/topics/backend/gin/index.md @@ -0,0 +1,15 @@ +--- +id: backend.gin.index +title: Gin Web 框架 +type: index +domain: backend +stack: [gin] +tags: [] +week: [1, 2, 3] +--- + +# Gin Web 框架 + +路由、参数绑定、中间件、鉴权、统一错误处理。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/go/index.md b/topics/backend/go/index.md new file mode 100644 index 0000000..d5295b4 --- /dev/null +++ b/topics/backend/go/index.md @@ -0,0 +1,15 @@ +--- +id: backend.go.index +title: Go 语言 +type: index +domain: backend +stack: [go] +tags: [] +week: [1, 2, 3, 14] +--- + +# Go 语言 + +语法、接口、错误处理、并发、测试和工程化。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/grpc-microservices/index.md b/topics/backend/grpc-microservices/index.md new file mode 100644 index 0000000..5aa34e1 --- /dev/null +++ b/topics/backend/grpc-microservices/index.md @@ -0,0 +1,15 @@ +--- +id: backend.grpc-microservices.index +title: gRPC 与微服务 +type: index +domain: backend +stack: [grpc-microservices] +tags: [] +week: [14] +--- + +# gRPC 与微服务 + +proto、四种调用方式、超时重试、服务治理、分布式事务。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/mq/index.md b/topics/backend/mq/index.md new file mode 100644 index 0000000..dbd2ba2 --- /dev/null +++ b/topics/backend/mq/index.md @@ -0,0 +1,15 @@ +--- +id: backend.mq.index +title: 消息队列(RabbitMQ / Kafka) +type: index +domain: backend +stack: [mq] +tags: [] +week: [3, 14] +--- + +# 消息队列(RabbitMQ / Kafka) + +异步解耦、可靠投递、幂等消费、顺序、延迟消息。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/mysql/index.md b/topics/backend/mysql/index.md new file mode 100644 index 0000000..4066284 --- /dev/null +++ b/topics/backend/mysql/index.md @@ -0,0 +1,15 @@ +--- +id: backend.mysql.index +title: MySQL +type: index +domain: backend +stack: [mysql] +tags: [] +week: [2, 14] +--- + +# MySQL + +InnoDB 索引、EXPLAIN、事务隔离与锁、慢查询、分库分表与主从。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/postgresql/index.md b/topics/backend/postgresql/index.md new file mode 100644 index 0000000..dcabbeb --- /dev/null +++ b/topics/backend/postgresql/index.md @@ -0,0 +1,15 @@ +--- +id: backend.postgresql.index +title: PostgreSQL +type: index +domain: backend +stack: [postgresql] +tags: [] +week: [2, 3, 6] +--- + +# PostgreSQL + +表设计、SQL、索引与 EXPLAIN、事务与 MVCC、JSONB、pgvector。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/backend/redis/index.md b/topics/backend/redis/index.md new file mode 100644 index 0000000..b6962fd --- /dev/null +++ b/topics/backend/redis/index.md @@ -0,0 +1,15 @@ +--- +id: backend.redis.index +title: Redis +type: index +domain: backend +stack: [redis] +tags: [] +week: [3, 6, 14] +--- + +# Redis + +数据结构、缓存模式、分布式锁、限流、Streams。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/devops/cicd/index.md b/topics/devops/cicd/index.md new file mode 100644 index 0000000..81a21bc --- /dev/null +++ b/topics/devops/cicd/index.md @@ -0,0 +1,15 @@ +--- +id: devops.cicd.index +title: CI/CD +type: index +domain: devops +stack: [cicd] +tags: [] +week: [3, 7, 14] +--- + +# CI/CD + +流水线设计、测试与构建、镜像发布、部署与回滚。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/devops/docker/index.md b/topics/devops/docker/index.md new file mode 100644 index 0000000..1809fdc --- /dev/null +++ b/topics/devops/docker/index.md @@ -0,0 +1,15 @@ +--- +id: devops.docker.index +title: Docker 与 Compose +type: index +domain: devops +stack: [docker] +tags: [] +week: [3, 6, 13, 14] +--- + +# Docker 与 Compose + +镜像、多阶段构建、网络、数据卷、Compose 编排。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/devops/git/index.md b/topics/devops/git/index.md new file mode 100644 index 0000000..b9f812d --- /dev/null +++ b/topics/devops/git/index.md @@ -0,0 +1,15 @@ +--- +id: devops.git.index +title: Git +type: index +domain: devops +stack: [git] +tags: [] +week: [1, 8, 15] +--- + +# Git + +分支模型、提交规范、合并与变基、误操作恢复、协作流程。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/devops/linux/index.md b/topics/devops/linux/index.md new file mode 100644 index 0000000..fb7ebc7 --- /dev/null +++ b/topics/devops/linux/index.md @@ -0,0 +1,15 @@ +--- +id: devops.linux.index +title: Linux 运维基础 +type: index +domain: devops +stack: [linux] +tags: [] +week: [14] +--- + +# Linux 运维基础 + +常用命令、进程与端口、日志、磁盘、权限、线上排查。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/devops/nginx/index.md b/topics/devops/nginx/index.md new file mode 100644 index 0000000..faad558 --- /dev/null +++ b/topics/devops/nginx/index.md @@ -0,0 +1,15 @@ +--- +id: devops.nginx.index +title: Nginx +type: index +domain: devops +stack: [nginx] +tags: [] +week: [3, 7, 14] +--- + +# Nginx + +反向代理、静态资源、HTTPS、SSE / WebSocket、限流、灰度。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/fe-testing-perf/index.md b/topics/frontend/fe-testing-perf/index.md new file mode 100644 index 0000000..a3699e2 --- /dev/null +++ b/topics/frontend/fe-testing-perf/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.fe-testing-perf.index +title: 前端测试与性能 +type: index +domain: frontend +stack: [fe-testing-perf] +tags: [] +week: [7] +--- + +# 前端测试与性能 + +Vitest、组件测试、Web Vitals、性能优化。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/react/index.md b/topics/frontend/react/index.md new file mode 100644 index 0000000..545aaba --- /dev/null +++ b/topics/frontend/react/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.react.index +title: React +type: index +domain: frontend +stack: [react] +tags: [] +week: [7] +--- + +# React + +Hooks、渲染与性能、状态管理、路由、流式界面。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/ssr/index.md b/topics/frontend/ssr/index.md new file mode 100644 index 0000000..1c639e4 --- /dev/null +++ b/topics/frontend/ssr/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.ssr.index +title: SSR(Nuxt / Next.js) +type: index +domain: frontend +stack: [ssr] +tags: [] +week: [7] +--- + +# SSR(Nuxt / Next.js) + +CSR / SSR / SSG、水合、Nuxt 与 Next.js 基础。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/typescript/index.md b/topics/frontend/typescript/index.md new file mode 100644 index 0000000..4ec6555 --- /dev/null +++ b/topics/frontend/typescript/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.typescript.index +title: TypeScript +type: index +domain: frontend +stack: [typescript] +tags: [] +week: [7] +--- + +# TypeScript + +类型系统、泛型、类型收窄、工程配置。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/vite/index.md b/topics/frontend/vite/index.md new file mode 100644 index 0000000..82daa55 --- /dev/null +++ b/topics/frontend/vite/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.vite.index +title: Vite +type: index +domain: frontend +stack: [vite] +tags: [] +week: [7] +--- + +# Vite + +开发服务器原理、构建、配置、插件、环境变量。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/vue/index.md b/topics/frontend/vue/index.md new file mode 100644 index 0000000..0f7add9 --- /dev/null +++ b/topics/frontend/vue/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.vue.index +title: Vue 3 + Pinia + Router +type: index +domain: frontend +stack: [vue] +tags: [] +week: [7] +--- + +# Vue 3 + Pinia + Router + +响应式、组合式 API、状态管理、路由与权限。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/frontend/webpack/index.md b/topics/frontend/webpack/index.md new file mode 100644 index 0000000..056e210 --- /dev/null +++ b/topics/frontend/webpack/index.md @@ -0,0 +1,15 @@ +--- +id: frontend.webpack.index +title: Webpack +type: index +domain: frontend +stack: [webpack] +tags: [] +week: [7] +--- + +# Webpack + +核心概念、Loader 与 Plugin、拆包、构建优化。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/index.md b/topics/index.md new file mode 100644 index 0000000..3e592ee --- /dev/null +++ b/topics/index.md @@ -0,0 +1,69 @@ +--- +id: topics.index +title: 专项学习总目录 +type: index +domain: plan +stack: [] +--- + +# 专项学习总目录 + +按技术栈组织的独立学习内容。每个技术栈包含:课程(lesson)、企业场景(scenario)、分级面试题(interview)和可运行的示例代码(examples)。16 周计划([plan/README.md](../plan/README.md))按周链接到这里。 + +跨技术栈的企业服务场景见 [scenarios/index.md](../scenarios/index.md)。内容规范见 [CONTRIBUTING.md](../CONTRIBUTING.md)。 + +## 后端(`backend`) + +| 技术栈 | 内容 | 用在第几周 | +| --- | --- | --- | +| [Go 语言](backend/go/index.md) | 语法、接口、错误处理、并发、测试和工程化 | 1、2、3、14 | +| [Gin Web 框架](backend/gin/index.md) | 路由、参数绑定、中间件、鉴权、统一错误处理 | 1、2、3 | +| [PostgreSQL](backend/postgresql/index.md) | 表设计、SQL、索引与 EXPLAIN、事务与 MVCC、JSONB、pgvector | 2、3、6 | +| [MySQL](backend/mysql/index.md) | InnoDB 索引、EXPLAIN、事务隔离与锁、慢查询、分库分表与主从 | 2、14 | +| [Redis](backend/redis/index.md) | 数据结构、缓存模式、分布式锁、限流、Streams | 3、6、14 | +| [消息队列(RabbitMQ / Kafka)](backend/mq/index.md) | 异步解耦、可靠投递、幂等消费、顺序、延迟消息 | 3、14 | +| [gRPC 与微服务](backend/grpc-microservices/index.md) | proto、四种调用方式、超时重试、服务治理、分布式事务 | 14 | + +## 运维与工程(`devops`) + +| 技术栈 | 内容 | 用在第几周 | +| --- | --- | --- | +| [Docker 与 Compose](devops/docker/index.md) | 镜像、多阶段构建、网络、数据卷、Compose 编排 | 3、6、13、14 | +| [Nginx](devops/nginx/index.md) | 反向代理、静态资源、HTTPS、SSE / WebSocket、限流、灰度 | 3、7、14 | +| [Linux 运维基础](devops/linux/index.md) | 常用命令、进程与端口、日志、磁盘、权限、线上排查 | 14 | +| [CI/CD](devops/cicd/index.md) | 流水线设计、测试与构建、镜像发布、部署与回滚 | 3、7、14 | +| [Git](devops/git/index.md) | 分支模型、提交规范、合并与变基、误操作恢复、协作流程 | 1、8、15 | + +## Python(`python`) + +| 技术栈 | 内容 | 用在第几周 | +| --- | --- | --- | +| [Python 语言](python/python/index.md) | 给 JS 开发者的 Python:语法、类型、异常、包管理、测试 | 4 | +| [asyncio 异步编程](python/asyncio/index.md) | 协程、任务、并发控制、超时与取消 | 4、5、12 | +| [FastAPI](python/fastapi/index.md) | 路由与校验、依赖注入、中间件与鉴权、流式输出、测试 | 4、5、12 | + +## AI 应用(`ai`) + +| 技术栈 | 内容 | 用在第几周 | +| --- | --- | --- | +| [RAG 检索增强生成](ai/rag/index.md) | 加载切分、嵌入、检索、混合检索与重排、引用与拒答、评测 | 5、6 | +| [向量数据库](ai/vector-db/index.md) | 近似最近邻索引、距离度量、Chroma / Milvus / pgvector 选型 | 5、6 | +| [LangChain](ai/langchain/index.md) | 模型与消息、LCEL、工具、结构化输出 | 6、11 | +| [LangGraph](ai/langgraph/index.md) | 状态图、条件路由、检查点续跑、interrupt、长期记忆 | 11、12 | +| [MCP 模型上下文协议](ai/mcp/index.md) | 协议概念、tools / resources / prompts、服务端与客户端 | 10、11 | +| [Function Calling 工具调用](ai/function-calling/index.md) | 工具定义、调用循环、参数校验、安全 | 10 | +| [提示词与上下文工程](ai/prompt-engineering/index.md) | 提示词结构、结构化输出、上下文工程、提示词注入防护 | 5、11、13 | +| [Agent 记忆、评测与可观测性](ai/agent-ops/index.md) | 短期 / 长期记忆、评测集、LLM 评分、追踪、成本 | 12、13 | +| [Dify / Coze 低代码平台](ai/lowcode/index.md) | 知识库、工作流、插件,和写代码的取舍 | 13 | + +## 前端(`frontend`) + +| 技术栈 | 内容 | 用在第几周 | +| --- | --- | --- | +| [Vue 3 + Pinia + Router](frontend/vue/index.md) | 响应式、组合式 API、状态管理、路由与权限 | 7 | +| [React](frontend/react/index.md) | Hooks、渲染与性能、状态管理、路由、流式界面 | 7 | +| [TypeScript](frontend/typescript/index.md) | 类型系统、泛型、类型收窄、工程配置 | 7 | +| [Vite](frontend/vite/index.md) | 开发服务器原理、构建、配置、插件、环境变量 | 7 | +| [Webpack](frontend/webpack/index.md) | 核心概念、Loader 与 Plugin、拆包、构建优化 | 7 | +| [SSR(Nuxt / Next.js)](frontend/ssr/index.md) | CSR / SSR / SSG、水合、Nuxt 与 Next.js 基础 | 7 | +| [前端测试与性能](frontend/fe-testing-perf/index.md) | Vitest、组件测试、Web Vitals、性能优化 | 7 | diff --git a/topics/python/asyncio/index.md b/topics/python/asyncio/index.md new file mode 100644 index 0000000..4259028 --- /dev/null +++ b/topics/python/asyncio/index.md @@ -0,0 +1,15 @@ +--- +id: python.asyncio.index +title: asyncio 异步编程 +type: index +domain: python +stack: [asyncio] +tags: [] +week: [4, 5, 12] +--- + +# asyncio 异步编程 + +协程、任务、并发控制、超时与取消。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/python/fastapi/index.md b/topics/python/fastapi/index.md new file mode 100644 index 0000000..e0c3b37 --- /dev/null +++ b/topics/python/fastapi/index.md @@ -0,0 +1,15 @@ +--- +id: python.fastapi.index +title: FastAPI +type: index +domain: python +stack: [fastapi] +tags: [] +week: [4, 5, 12] +--- + +# FastAPI + +路由与校验、依赖注入、中间件与鉴权、流式输出、测试。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。 diff --git a/topics/python/python/index.md b/topics/python/python/index.md new file mode 100644 index 0000000..c0ebe0e --- /dev/null +++ b/topics/python/python/index.md @@ -0,0 +1,15 @@ +--- +id: python.python.index +title: Python 语言 +type: index +domain: python +stack: [python] +tags: [] +week: [4] +--- + +# Python 语言 + +给 JS 开发者的 Python:语法、类型、异常、包管理、测试。 + +> 本专题建设中:课程、企业场景、面试题和示例代码会陆续补充。