lesson_content.py 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259
  1. """
  2. 课程内容 - 为每个课程提供丰富的Markdown内容
  3. """
  4. from typing import Optional
  5. def get_lesson_content(lesson_id: str, title: str, lesson_type: str, description: str) -> str:
  6. """根据课程ID返回对应的Markdown内容"""
  7. # 优先查找特定课程的内容
  8. custom = _get_custom_content(lesson_id, title)
  9. if custom:
  10. return custom
  11. # 通用模板
  12. return _get_generic_content(title, description, lesson_type)
  13. def _get_custom_content(lesson_id: str, title: str) -> Optional[str]:
  14. """为特定课程ID返回个性化内容"""
  15. content_map = {
  16. # ======== 前端 - HTML/CSS ========
  17. "fe-html-01": """## 学习目标
  18. - 理解 HTML 文档的基本结构
  19. - 掌握 DOCTYPE、html、head、body 等核心标签
  20. - 了解 meta 标签的常见用法
  21. ## HTML 文档的基本结构
  22. 每个 HTML 文档都遵循一个基本的骨架结构:
  23. ```html
  24. <!DOCTYPE html>
  25. <html lang="zh-CN">
  26. <head>
  27. <meta charset="UTF-8">
  28. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  29. <title>文档标题</title>
  30. </head>
  31. <body>
  32. <!-- 页面可见内容 -->
  33. <h1>Hello, World!</h1>
  34. <p>这是我的第一个网页。</p>
  35. </body>
  36. </html>
  37. ```
  38. ### 各部分作用
  39. | 标签 | 作用 |
  40. |------|------|
  41. | `<!DOCTYPE html>` | 声明文档类型为 HTML5 |
  42. | `<html>` | 文档的根元素,所有内容包含在内 |
  43. | `<head>` | 文档的元数据区(不可见) |
  44. | `<body>` | 文档的内容区(用户可见) |
  45. ### `<head>` 中的常用标签
  46. - **`<title>`** — 浏览器标签页显示的标题,对 SEO 也很重要
  47. - **`<meta charset="UTF-8">`** — 设置字符编码,避免乱码
  48. - **`<meta name="viewport">`** — 移动端适配声明
  49. - **`<link>`** — 引入外部 CSS 文件
  50. - **`<style>`** — 内嵌 CSS 样式
  51. ## 练习
  52. 创建一个包含以下内容的 HTML 文件:
  53. 1. 正确的文档结构声明
  54. 2. 设置标题为"我的第一个网页"
  55. 3. 在 body 中添加一个一级标题和一个段落
  56. > 💡 **提示**:使用 VS Code 新建 `.html` 文件后,输入 `!` 并按 Tab 可以快速生成 HTML5 骨架。
  57. """,
  58. "fe-html-02": """## 学习目标
  59. - 掌握常用 HTML 标签的语义和用法
  60. - 理解块级元素与行内元素的区别
  61. - 学会使用列表、图片、链接等构建内容
  62. ## 常用标签
  63. ### 文本标签
  64. ```html
  65. <!-- 标题 -->
  66. <h1>一级标题</h1>
  67. <h2>二级标题</h2>
  68. <h3>三级标题</h3>
  69. <!-- 段落与文本 -->
  70. <p>这是一个段落。</p>
  71. <strong>加重要内容</strong>
  72. <em>强调文本</em>
  73. <br> <!-- 换行 -->
  74. ```
  75. ### 列表
  76. ```html
  77. <!-- 无序列表 -->
  78. <ul>
  79. <li>苹果</li>
  80. <li>香蕉</li>
  81. <li>橘子</li>
  82. </ul>
  83. <!-- 有序列表 -->
  84. <ol>
  85. <li>第一步:打开编辑器</li>
  86. <li>第二步:编写代码</li>
  87. <li>第三步:保存文件</li>
  88. </ol>
  89. ```
  90. ### 链接与图片
  91. ```html
  92. <!-- 链接 -->
  93. <a href="https://example.com" target="_blank">打开示例网站</a>
  94. <!-- 图片 -->
  95. <img src="logo.png" alt="网站Logo" width="200">
  96. ```
  97. > ⚠️ **注意**:`<a>` 的 `target="_blank"` 会在新标签页打开链接。`<img>` 的 `alt` 属性用于图片加载失败时的替代文本,对无障碍访问很重要。
  98. ## 块级 vs 行内元素
  99. | 类别 | 特点 | 例子 |
  100. |------|------|------|
  101. | **块级元素** | 独占一行,可设置宽高 | `div`, `h1`-`h6`, `p`, `ul`, `ol` |
  102. | **行内元素** | 不换行,宽高由内容决定 | `span`, `a`, `strong`, `em`, `img` |
  103. ## 练习
  104. 创建一个"我的兴趣爱好"页面,包含:
  105. 1. 一个二级标题
  106. 2. 一段自我介绍
  107. 3. 一个无序列表列出你的兴趣(至少3项)
  108. 4. 一张图片和指向你最喜欢网站的外部链接
  109. """,
  110. "fe-css-01": """## 学习目标
  111. - 理解 CSS 的作用和基本语法
  112. - 掌握三种选择器:元素、类、ID
  113. - 了解选择器的优先级规则
  114. ## CSS 基本语法
  115. ```css
  116. 选择器 {
  117. 属性名: 属性值;
  118. 属性名: 属性值;
  119. }
  120. ```
  121. ### 引入 CSS 的方式
  122. **1. 外部样式表(推荐)**
  123. ```html
  124. <link rel="stylesheet" href="style.css">
  125. ```
  126. **2. 内部样式表**
  127. ```html
  128. <style>
  129. p {{ color: red; }}
  130. </style>
  131. ```
  132. **3. 行内样式(不推荐)**
  133. ```html
  134. <p style="color: red;">这段文字是红色</p>
  135. ```
  136. ## 三种基本选择器
  137. ### 元素选择器
  138. 选中所有该类型的标签:
  139. ```css
  140. p {{ color: #333; }}
  141. h1 {{ font-size: 24px; }}
  142. ```
  143. ### 类选择器(`.`)
  144. 选中所有带有该 class 的元素,可重复使用:
  145. ```css
  146. .highlight {{ background-color: yellow; }}
  147. .card {{ border: 1px solid #ccc; }}
  148. ```
  149. ```html
  150. <p class="highlight">这段有高亮背景</p>
  151. <div class="card">这是一个卡片</div>
  152. ```
  153. ### ID 选择器(`#`)
  154. **唯一**,一个页面中每个 ID 只能使用一次:
  155. ```css
  156. #header {{ height: 60px; }}
  157. #main-content {{ padding: 20px; }}
  158. ```
  159. ```html
  160. <div id="header">页面头部</div>
  161. ```
  162. ## 优先级(权重)
  163. 当多个选择器冲突时,按权重决定:
  164. | 选择器 | 权重 | 示例 |
  165. |--------|------|------|
  166. | 元素选择器 | 最低 | `p`、`h1` |
  167. | 类选择器 | 中等 | `.card`、`.highlight` |
  168. | ID选择器 | 最高 | `#header` |
  169. | 行内样式 | 更高 | `style="..."` |
  170. | `!important` | 最高(慎用) | `color: red !important` |
  171. > 🧪 **实验**:给同一个元素同时设置类和 ID 样式,观察哪个生效。
  172. ## 练习
  173. 创建一个 HTML 页面并添加 CSS:
  174. 1. 用元素选择器设置全局字体
  175. 2. 用类选择器创建两个不同颜色的卡片
  176. 3. 用 ID 选择器设置页面标题的样式
  177. """,
  178. "fe-css-02": """## 学习目标
  179. - 理解盒模型的四个组成部分
  180. - 掌握 width/height、padding、border、margin 的用法
  181. - 学会使用 `box-sizing` 控制盒模型行为
  182. ## 盒模型
  183. 每个 HTML 元素都可以看作一个"盒子",从内到外包含:
  184. ```
  185. ┌─────────────────────────────────┐
  186. │ Margin (外边距) │
  187. │ ┌───────────────────────────┐ │
  188. │ │ Border (边框) │ │
  189. │ │ ┌─────────────────────┐ │ │
  190. │ │ │ Padding (内边距) │ │ │
  191. │ │ │ ┌───────────────┐ │ │ │
  192. │ │ │ │ Content │ │ │ │
  193. │ │ │ │ (内容区域) │ │ │ │
  194. │ │ │ └───────────────┘ │ │ │
  195. │ │ └─────────────────────┘ │ │
  196. │ └───────────────────────────┘ │
  197. └─────────────────────────────────┘
  198. ```
  199. ### 代码示例
  200. ```css
  201. .box {{
  202. width: 200px;
  203. padding: 20px; /* 内容与边框之间的距离 */
  204. border: 2px solid #333; /* 边框 */
  205. margin: 10px; /* 盒子与其他元素的距离 */
  206. }}
  207. ```
  208. ### 盒模型的计算
  209. 默认情况下(`box-sizing: content-box`):
  210. **实际宽度 = width + padding × 2 + border × 2**
  211. 这意味着 `width: 200px` 加上 `padding: 20px` 和 `border: 2px` 后,实际占用的宽度是 **244px**!
  212. ### `box-sizing: border-box`
  213. 推荐做法——让 width 包含 padding 和 border:
  214. ```css
  215. * {{
  216. box-sizing: border-box;
  217. }}
  218. ```
  219. 这样 `width: 200px` 就是最终渲染宽度,padding 和 border 向内压缩。
  220. ## display 属性
  221. | 值 | 行为 |
  222. |----|------|
  223. | `block` | 块级,独占一行 |
  224. | `inline` | 行内,不换行 |
  225. | `inline-block` | 行内但可设宽高 |
  226. | `none` | 隐藏元素,不占空间 |
  227. ## 练习
  228. 用 HTML + CSS 实现下图效果(描述:三个卡片并排,每个卡片有标题、文字、边框和间距):
  229. 1. 三个 `div` 卡片横向排列
  230. 2. 每个卡片有 1px 边框、16px 内边距
  231. 3. 卡片之间用 margin 隔开
  232. 4. 使用 `box-sizing: border-box`
  233. """,
  234. "fe-css-03": """## 学习目标
  235. - 理解 Flexbox 的核心概念:主轴与交叉轴
  236. - 掌握容器属性和项目属性
  237. - 能使用 Flexbox 实现常见布局
  238. ## Flexbox 核心概念
  239. Flexbox 是一种一维布局模型,适合在**一行或一列**中排列元素。
  240. ```css
  241. .container {{
  242. display: flex; /* 开启 Flexbox */
  243. }}
  244. ```
  245. ### 主轴与交叉轴
  246. - **主轴(main axis)** — `flex-direction` 决定的方向
  247. - **交叉轴(cross axis)** — 与主轴垂直的方向
  248. ```
  249. flex-direction: row; → 主轴水平,从左到右
  250. flex-direction: column; → 主轴垂直,从上到下
  251. ```
  252. ## 容器属性
  253. ```css
  254. .container {{
  255. display: flex;
  256. flex-direction: row; /* row | column | row-reverse | column-reverse */
  257. justify-content: center; /* 主轴对齐方式 */
  258. align-items: center; /* 交叉轴对齐方式 */
  259. flex-wrap: wrap; /* 是否换行 */
  260. gap: 16px; /* 项目间距(推荐) */
  261. }}
  262. ```
  263. ### justify-content
  264. ```
  265. flex-start ┃ [项目1][项目2][项目3]
  266. center ┃ [项目1][项目2][项目3]
  267. space-between ┃ [项目1] [项目2] [项目3]
  268. space-around ┃ [项目1] [项目2] [项目3]
  269. ```
  270. ### align-items
  271. ```
  272. stretch ┃ 项目高度拉伸填满容器(默认)
  273. center ┃ 项目在交叉轴居中
  274. flex-start ┃ 项目在交叉轴起始位置
  275. ```
  276. ## 项目属性
  277. ```css
  278. .item {{
  279. flex: 1; /* 分配剩余空间的比例 */
  280. align-self: center; /* 单独对齐 */
  281. order: 2; /* 排列顺序(越小越前) */
  282. }}
  283. ```
  284. ## 常见布局示例
  285. ### 水平居中
  286. ```css
  287. .parent {{
  288. display: flex;
  289. justify-content: center;
  290. align-items: center;
  291. }}
  292. ```
  293. ### 两端对齐导航
  294. ```css
  295. .nav {{
  296. display: flex;
  297. justify-content: space-between;
  298. align-items: center;
  299. }}
  300. ```
  301. ### 响应式卡片网格
  302. ```css
  303. .grid {{
  304. display: flex;
  305. flex-wrap: wrap;
  306. gap: 20px;
  307. }}
  308. .card {{
  309. flex: 1 1 300px; /* 最小300px,自动换行 */
  310. }}
  311. ```
  312. ## 练习
  313. 用 Flexbox 实现一个导航栏:
  314. - 左侧是 Logo
  315. - 中间是导航链接(首页、关于、服务、联系)
  316. - 右侧是登录/注册按钮
  317. - 垂直居中
  318. """,
  319. # ======== 前端 - JavaScript ========
  320. "fe-js-01": """## 学习目标
  321. - 理解 `let`、`const`、`var` 的区别
  322. - 掌握 JavaScript 的基本数据类型
  323. - 了解引用类型与基本类型的差异
  324. ## 变量声明
  325. ### `let` vs `const` vs `var`
  326. | 关键字 | 可修改 | 作用域 | 推荐 |
  327. |--------|--------|--------|------|
  328. | `const` | ❌ 不可重新赋值 | 块级作用域 | **默认选择** |
  329. | `let` | ✅ 可重新赋值 | 块级作用域 | 需要改变时使用 |
  330. | `var` | ✅ 可重新赋值 | 函数作用域 | ❌ 避免使用 |
  331. ```javascript
  332. const PI = 3.14159;
  333. let count = 0;
  334. count = 1; // ✅ 可以
  335. // 常见错误
  336. const user = {{ name: 'Alice' }};
  337. user.name = 'Bob'; // ✅ const 对象的内容可以修改
  338. user = {{ name: 'Bob' }}; // ❌ 不能重新赋值
  339. ```
  340. ## 基本数据类型
  341. | 类型 | 示例 | 说明 |
  342. |------|------|------|
  343. | `number` | `42`, `3.14` | 整数和浮点数 |
  344. | `string` | `'hello'`, `"world"` | 文本 |
  345. | `boolean` | `true`, `false` | 布尔值 |
  346. | `null` | `null` | 空值 |
  347. | `undefined` | `undefined` | 未定义 |
  348. | `symbol` | `Symbol()` | 唯一标识符 |
  349. ```javascript
  350. const name = 'Alice';
  351. const age = 25;
  352. const isStudent = true;
  353. const score = null;
  354. let grade; // undefined
  355. // typeof 运算符
  356. console.log(typeof name); // "string"
  357. console.log(typeof age); // "number"
  358. ```
  359. ### 动态类型
  360. JavaScript 是动态类型语言,变量可以随时改变类型:
  361. ```javascript
  362. let value = 'hello';
  363. value = 42; // 变成了 number
  364. value = true; // 变成了 boolean
  365. ```
  366. ### 类型转换
  367. ```javascript
  368. // 隐式转换
  369. const result = '5' - 2; // 3 (字符串转数字)
  370. const msg = '结果是: ' + 42; // "结果是: 42"
  371. // 显式转换
  372. Number('42') // 42
  373. String(42) // "42"
  374. Boolean(0) // false
  375. Boolean('') // false
  376. Boolean('hello') // true
  377. ```
  378. > ⚠️ **常见陷阱**:`'5' + 2` 结果是 `'52'`(字符串拼接),而 `'5' - 2` 结果是 `3`(数值减法)。
  379. ## 引用类型
  380. 对象和数组是引用类型,赋值传递的是引用:
  381. ```javascript
  382. const a = {{ name: 'Alice' }};
  383. const b = a; // b 引用同一个对象
  384. b.name = 'Bob';
  385. console.log(a.name); // "Bob" — a 也被改了!
  386. ```
  387. ## 练习
  388. 1. 用 `const` 定义一个对象,包含你的姓名、年龄和爱好
  389. 2. 用 `let` 定义一个计数器,从 0 递增到 3
  390. 3. 分别使用 `typeof` 检查 `null`、`[]`、`{{}}` 的类型
  391. """,
  392. "fe-js-02": """## 学习目标
  393. - 掌握函数定义的多种方式
  394. - 理解作用域和闭包的概念
  395. - 了解箭头函数的特性
  396. ## 函数定义
  397. ### 函数声明 vs 函数表达式
  398. ```javascript
  399. // 函数声明(会被提升)
  400. function add(a, b) {{
  401. return a + b;
  402. }}
  403. // 函数表达式(不会被提升)
  404. const multiply = function(a, b) {{
  405. return a * b;
  406. }};
  407. ```
  408. ### 箭头函数
  409. ```javascript
  410. // 基本语法
  411. const add = (a, b) => a + b;
  412. const square = x => x * x; // 一个参数可省略括号
  413. const greet = () => 'Hello!';
  414. // 多行需要 {{}} 和 return
  415. const sum = (a, b) => {{
  416. const result = a + b;
  417. return result;
  418. }};
  419. ```
  420. ### 箭头函数 vs 普通函数
  421. | 区别 | 普通函数 | 箭头函数 |
  422. |------|----------|----------|
  423. | `this` | 动态绑定 | 继承外层作用域 |
  424. | `arguments` | 有 | 没有 |
  425. | 作为构造函数 | ✅ | ❌ |
  426. ## 作用域
  427. ```javascript
  428. const global = '全局变量';
  429. function outer() {{
  430. const outerVar = '外部函数变量';
  431. function inner() {{
  432. const innerVar = '内部函数变量';
  433. console.log(global); // ✅ 可访问
  434. console.log(outerVar); // ✅ 可访问
  435. }}
  436. console.log(innerVar); // ❌ 不可访问
  437. }}
  438. ```
  439. ## 闭包
  440. 函数 + 其被创建时所在的作用域环境的组合:
  441. ```javascript
  442. function createCounter() {{
  443. let count = 0;
  444. return function() {{
  445. count++;
  446. return count;
  447. }};
  448. }}
  449. const counter = createCounter();
  450. console.log(counter()); // 1
  451. console.log(counter()); // 2
  452. console.log(counter()); // 3
  453. ```
  454. > 💡 **用途**:数据私有化、函数工厂、模块模式
  455. ## 练习
  456. 1. 写一个箭头函数 `isEven(n)` 判断数字是否为偶数
  457. 2. 用闭包实现一个 `makeMultiplier(x)`,返回一个乘以 `x` 的函数
  458. 3. 比较普通函数和箭头函数中 `this` 的行为差异
  459. """,
  460. # ======== 前端 - Vue ========
  461. "fe-vue-01": """## 学习目标
  462. - 理解 Vue 3 的核心概念
  463. - 掌握 `ref` 和 `reactive` 响应式 API
  464. - 学会使用模板语法
  465. ## 什么是 Vue?
  466. Vue 是一个用于构建用户界面的**渐进式框架**。核心特性:
  467. - **声明式渲染** — 通过模板语法将数据绑定到 DOM
  468. - **响应式系统** — 数据变化自动更新视图
  469. - **组件化** — UI 拆分为独立的可复用组件
  470. ## 创建 Vue 应用
  471. ```javascript
  472. import {{ createApp, ref }} from 'vue'
  473. createApp({{
  474. setup() {{
  475. const count = ref(0)
  476. const increment = () => count.value++
  477. return {{ count, increment }}
  478. }}
  479. }}).mount('#app')
  480. ```
  481. ```html
  482. <div id="app">
  483. <p>计数: {{ "{{ count }}" }}</p>
  484. <button @click="increment">+1</button>
  485. </div>
  486. ```
  487. ## 响应式 API
  488. ### `ref` — 基本响应式
  489. ```javascript
  490. import {{ ref }} from 'vue'
  491. const count = ref(0)
  492. console.log(count.value) // 0
  493. count.value = 1
  494. ```
  495. > 在模板中使用时自动解包,不需要 `.value`
  496. ### `reactive` — 对象响应式
  497. ```javascript
  498. import {{ reactive }} from 'vue'
  499. const user = reactive({{
  500. name: 'Alice',
  501. age: 25
  502. }})
  503. user.age = 26 // 直接修改,无需 .value
  504. ```
  505. ### `computed` — 计算属性
  506. ```javascript
  507. import {{ ref, computed }} from 'vue'
  508. const price = ref(100)
  509. const quantity = ref(2)
  510. const total = computed(() => price.value * quantity.value)
  511. ```
  512. ## 模板语法
  513. ```html
  514. <!-- 文本插值 -->
  515. <p>{{ "{{ message }}" }}</p>
  516. <!-- 属性绑定 -->
  517. <img :src="imageUrl">
  518. <!-- 事件绑定 -->
  519. <button @click="handleClick">点击</button>
  520. <!-- 条件渲染 -->
  521. <p v-if="isVisible">可见</p>
  522. <!-- 列表渲染 -->
  523. <li v-for="(item, index) in items" :key="index">{{ "{{ item }}" }}</li>
  524. <!-- 双向绑定 -->
  525. <input v-model="username">
  526. ```
  527. ## 练习
  528. 创建一个简单的 Vue 应用:
  529. 1. 用 `ref` 定义用户名和年龄
  530. 2. 用 `computed` 计算是否成年(>=18)
  531. 3. 在模板中展示这些数据
  532. """,
  533. # ======== 后端 - Python ========
  534. "be-py-01": """## 学习目标
  535. - 回顾 Python 基础语法
  536. - 理解列表推导式、装饰器等进阶用法
  537. - 掌握 Python 常见最佳实践
  538. ## Python 基础回顾
  539. ```python
  540. # 变量与类型
  541. name: str = "Python"
  542. version: float = 3.11
  543. # 列表推导式
  544. squares = [x**2 for x in range(10) if x % 2 == 0]
  545. # 字典操作
  546. user = {{"name": "Alice", "age": 25}}
  547. print(user.get("name", "Unknown"))
  548. ```
  549. ## 装饰器
  550. 装饰器是一种在不修改原函数代码的情况下扩展其功能的方式:
  551. ```python
  552. from functools import wraps
  553. def log_calls(func):
  554. @wraps(func)
  555. def wrapper(*args, **kwargs):
  556. print(f"[LOG] 调用 {{func.__name__}}")
  557. result = func(*args, **kwargs)
  558. print(f"[LOG] {{func.__name__}} 返回 {{result}}")
  559. return result
  560. return wrapper
  561. @log_calls
  562. def add(a, b):
  563. return a + b
  564. add(3, 5)
  565. # [LOG] 调用 add
  566. # [LOG] add 返回 8
  567. ```
  568. ## 上下文管理器
  569. ```python
  570. # 使用 with 语句
  571. with open("file.txt", "r") as f:
  572. content = f.read()
  573. # 自定义上下文管理器
  574. from contextlib import contextmanager
  575. @contextmanager
  576. def timer():
  577. import time
  578. start = time.time()
  579. try:
  580. yield
  581. finally:
  582. elapsed = time.time() - start
  583. print(f"耗时: {{elapsed:.2f}}秒")
  584. with timer():
  585. sum(range(1000000))
  586. ```
  587. ## 类型提示
  588. ```python
  589. from typing import List, Optional, Dict
  590. def process_users(users: List[Dict[str, str]]) -> List[str]:
  591. \"\"\"提取所有用户名\"\"\"
  592. return [u.get("name", "") for u in users]
  593. def find_user(id: int) -> Optional[Dict[str, str]]:
  594. \"\"\"根据 ID 查找用户\"\"\"
  595. return None # 未找到
  596. ```
  597. ## 练习
  598. 1. 编写一个装饰器 `@retry(max_attempts=3)`,让函数在抛出异常时自动重试
  599. 2. 写一个上下文管理器,用于测量代码块的执行时间
  600. 3. 使用类型提示定义一个函数签名,处理用户列表数据
  601. """,
  602. "be-py-02": """## 学习目标
  603. - 理解文件读写的基本模式
  604. - 掌握异常处理的正确方式
  605. - 学会使用标准库处理常见任务
  606. ## 文件操作
  607. ```python
  608. # 推荐方式:使用 with 语句
  609. with open("data.txt", "r", encoding="utf-8") as f:
  610. content = f.read()
  611. # 逐行读取
  612. with open("data.txt", "r") as f:
  613. for line in f:
  614. print(line.strip())
  615. # 写入文件
  616. with open("output.txt", "w") as f:
  617. f.write("Hello, World!\\n")
  618. ```
  619. ## 异常处理
  620. ```python
  621. try:
  622. result = 10 / 0
  623. except ZeroDivisionError as e:
  624. print(f"不能除以零: {{e}}")
  625. except ValueError as e:
  626. print(f"值错误: {{e}}")
  627. except Exception as e:
  628. print(f"未知错误: {{e}}")
  629. else:
  630. print("没有发生异常")
  631. finally:
  632. print("总是执行")
  633. ```
  634. ### 自定义异常
  635. ```python
  636. class ValidationError(Exception):
  637. \"\"\"数据验证失败\"\"\"
  638. pass
  639. def validate_age(age: int):
  640. if age < 0 or age > 150:
  641. raise ValidationError(f"无效年龄: {{age}}")
  642. ```
  643. ## 标准库常用模块
  644. ```python
  645. import json
  646. import os
  647. import sys
  648. from datetime import datetime, timedelta
  649. # JSON 处理
  650. data = {{"name": "Alice", "age": 25}}
  651. json_str = json.dumps(data, ensure_ascii=False)
  652. parsed = json.loads(json_str)
  653. # 路径操作
  654. path = os.path.join("data", "subdir", "file.txt")
  655. print(os.path.exists(path))
  656. # 日期时间
  657. now = datetime.now()
  658. tomorrow = now + timedelta(days=1)
  659. print(now.strftime("%Y-%m-%d %H:%M:%S"))
  660. ```
  661. ## 练习
  662. 1. 读取一个 JSON 配置文件,解析其中的设置
  663. 2. 编写一个函数,安全地将字符串转换为整数,转换失败时返回 None
  664. 3. 使用 `os` 模块遍历一个目录下的所有 Python 文件
  665. 4. 使用 `datetime` 计算距离下个生日还有多少天
  666. """,
  667. # ======== 后端 - API ========
  668. "be-api-01": """## 学习目标
  669. - 理解 REST API 的核心原则
  670. - 掌握 HTTP 方法、状态码的正确使用
  671. - 学会设计资源导向的 URL
  672. ## REST 核心原则
  673. REST(Representational State Transfer)是一种 API 设计风格:
  674. 1. **资源导向** — URL 表示资源(名词),而不是操作(动词)
  675. 2. **HTTP 方法表示操作** — GET/ POST/ PUT/ DELETE
  676. 3. **无状态** — 每个请求包含所有必要信息
  677. 4. **统一接口** — 一致的 URL 模式和响应格式
  678. ## HTTP 方法
  679. | 方法 | 作用 | 幂等 | 请求体 |
  680. |------|------|------|--------|
  681. | GET | 获取资源 | ✅ | 通常无 |
  682. | POST | 创建资源 | ❌ | 有 |
  683. | PUT | 完整更新资源 | ✅ | 有 |
  684. | PATCH | 部分更新资源 | ❌ | 有 |
  685. | DELETE | 删除资源 | ✅ | 通常无 |
  686. ## 状态码
  687. | 状态码 | 含义 | 使用场景 |
  688. |--------|------|----------|
  689. | 200 OK | 请求成功 | GET、PUT 成功 |
  690. | 201 Created | 创建成功 | POST 创建资源 |
  691. | 204 No Content | 成功无返回体 | DELETE 成功 |
  692. | 400 Bad Request | 客户端请求错误 | 参数校验失败 |
  693. | 404 Not Found | 资源不存在 | 查询不存在的 ID |
  694. | 409 Conflict | 资源冲突 | 创建重复资源 |
  695. | 500 Internal Server Error | 服务器错误 | 未预期的异常 |
  696. ## URL 设计
  697. ```python
  698. # ✅ 好的设计(资源导向)
  699. GET /api/users # 获取用户列表
  700. GET /api/users/{{id}} # 获取单个用户
  701. POST /api/users # 创建用户
  702. PUT /api/users/{{id}} # 更新用户
  703. DELETE /api/users/{{id}} # 删除用户
  704. # ✅ 查询参数用于过滤/排序/分页
  705. GET /api/tasks?status=done&page=2&sort=created_at
  706. # ✅ 子资源
  707. GET /api/users/{{id}}/posts # 用户的文章列表
  708. # ❌ 不好的设计(动词在 URL 中)
  709. GET /api/getUser # ❌
  710. POST /api/createUser # ❌
  711. POST /api/deleteUser # ❌
  712. ```
  713. ## FastAPI 快速开始
  714. ```python
  715. from fastapi import FastAPI
  716. from pydantic import BaseModel
  717. app = FastAPI()
  718. class Item(BaseModel):
  719. name: str
  720. price: float
  721. @app.get("/items")
  722. async def list_items():
  723. return [{{"id": 1, "name": "Item 1", "price": 9.99}}]
  724. @app.post("/items")
  725. async def create_item(item: Item):
  726. return {{"id": 2, **item.model_dump()}}
  727. ```
  728. ## 练习
  729. 1. 为一个"博客系统"设计 RESTful API 端点(文章、评论、标签)
  730. 2. 说明每个端点的 HTTP 方法、URL、请求参数和响应状态码
  731. """,
  732. "be-api-02": """## 学习目标
  733. - 掌握 FastAPI 路由和参数处理
  734. - 理解请求体验证和响应模型
  735. - 学会使用依赖注入
  736. ## FastAPI 路由进阶
  737. ### 路径参数与查询参数
  738. ```python
  739. from fastapi import FastAPI, Query, Path
  740. app = FastAPI()
  741. @app.get("/users/{{user_id}}")
  742. async def get_user(
  743. user_id: int = Path(..., title="用户ID"),
  744. include_details: bool = Query(False, title="是否包含详情")
  745. ):
  746. return {{"user_id": user_id, "details": include_details}}
  747. ```
  748. ### 请求体验证
  749. ```python
  750. from pydantic import BaseModel, Field
  751. class CreateUserRequest(BaseModel):
  752. username: str = Field(..., min_length=3, max_length=50)
  753. email: str = Field(..., pattern=r"^[\\w.-]+@[\\w.-]+\\.\\w{{2,}}$")
  754. age: int = Field(ge=0, le=150)
  755. @app.post("/users")
  756. async def create_user(user: CreateUserRequest):
  757. return {{"message": "用户创建成功", "user": user}}
  758. ```
  759. ### 响应模型
  760. ```python
  761. from typing import List
  762. from pydantic import BaseModel
  763. class UserResponse(BaseModel):
  764. id: int
  765. username: str
  766. email: str
  767. @app.get("/users", response_model=List[UserResponse])
  768. async def list_users():
  769. return [
  770. UserResponse(id=1, username="alice", email="alice@example.com")
  771. ]
  772. ```
  773. ## 依赖注入
  774. ```python
  775. from fastapi import Depends, HTTPException
  776. def get_current_user(token: str = Query(...)):
  777. if token != "secret":
  778. raise HTTPException(status_code=401, detail="未授权")
  779. return {{"id": 1, "username": "alice"}}
  780. @app.get("/profile")
  781. async def get_profile(user: dict = Depends(get_current_user)):
  782. return user
  783. ```
  784. ## 错误处理
  785. ```python
  786. from fastapi import HTTPException
  787. from fastapi.responses import JSONResponse
  788. @app.get("/items/{{item_id}}")
  789. async def get_item(item_id: int):
  790. if item_id <= 0:
  791. raise HTTPException(
  792. status_code=400,
  793. detail="无效的项目ID"
  794. )
  795. # ... 查找项目
  796. return {{"id": item_id, "name": "Sample Item"}}
  797. ```
  798. ## 练习
  799. 1. 创建一个 Todo 的 CRUD API(使用内存列表存储)
  800. 2. 添加参数校验(标题非空、状态只能是 pending/done)
  801. 3. 使用响应模型控制返回字段
  802. """,
  803. # ======== 全栈 - Web基础 ========
  804. "fs-web-01": """## 学习目标
  805. - 理解 HTTP 协议的基本原理
  806. - 掌握请求-响应模型
  807. - 了解浏览器如何加载网页
  808. ## HTTP 协议
  809. HTTP(超文本传输协议)是 Web 的基础通信协议。
  810. ### 请求-响应模型
  811. ```
  812. 浏览器 服务器
  813. │ │
  814. ├── GET /index.html ──────────►│
  815. │ ├── 查找文件
  816. │◄── 200 OK + HTML 内容 ──────┤
  817. │ │
  818. ├── GET /style.css ───────────►│
  819. │◄── 200 OK + CSS 内容 ───────┤
  820. │ │
  821. ├── GET /app.js ──────────────►│
  822. │◄── 200 OK + JS 内容 ────────┤
  823. ```
  824. ### HTTP 请求结构
  825. ```
  826. GET /api/users HTTP/1.1
  827. Host: example.com
  828. Authorization: Bearer token123
  829. Content-Type: application/json
  830. {{"name": "Alice"}}
  831. ```
  832. ### HTTP 响应结构
  833. ```
  834. HTTP/1.1 200 OK
  835. Content-Type: application/json
  836. {{"id": 1, "name": "Alice"}}
  837. ```
  838. ## 常见请求头
  839. | 请求头 | 作用 |
  840. |--------|------|
  841. | `Authorization` | 认证信息 |
  842. | `Content-Type` | 请求体格式 |
  843. | `Accept` | 期望的响应格式 |
  844. | `User-Agent` | 客户端标识 |
  845. ## 常见响应头
  846. | 响应头 | 作用 |
  847. |--------|------|
  848. | `Content-Type` | 响应体格式 |
  849. | `Set-Cookie` | 设置 Cookie |
  850. | `Cache-Control` | 缓存策略 |
  851. | `Access-Control-Allow-Origin` | CORS 设置 |
  852. ## 浏览器加载流程
  853. 1. 解析 HTML → 构建 DOM 树
  854. 2. 加载 CSS → 构建 CSSOM 树
  855. 3. 合并为渲染树(Render Tree)
  856. 4. 布局(Layout)→ 计算位置和大小
  857. 5. 绘制(Paint)→ 渲染到屏幕
  858. > 💡 **关键**:CSS 会阻塞渲染,JavaScript 会阻塞解析。所以 `<script>` 标签通常放在 `</body>` 前。
  859. ## 练习
  860. 1. 用浏览器的开发者工具(F12)打开 Network 面板,访问一个网站,观察所有请求
  861. 2. 识别每个请求的类型(文档、样式、脚本、图片)
  862. 3. 查看一个 API 请求的请求头、响应头和响应体
  863. """,
  864. }
  865. # 检查是否有匹配的内容
  866. if lesson_id in content_map:
  867. return content_map[lesson_id]
  868. return None
  869. def _get_generic_content(title: str, description: str, lesson_type: str) -> str:
  870. """为没有个性化内容的课程生成通用内容"""
  871. type_headers = {
  872. "theory": "📖 理论学习",
  873. "practice": "💻 实践练习",
  874. "quiz": "❓ 知识测验",
  875. "project": "🚀 项目实战",
  876. }
  877. type_content = {
  878. "theory": """
  879. ## 概述
  880. **{title}** — {description}
  881. ### 学习要点
  882. 请跟随导师在对话中学习本课程的核心概念。导师将为你提供:
  883. 1. 详细的概念讲解和原理解析
  884. 2. 实际代码示例和最佳实践
  885. 3. 常见陷阱和注意事项
  886. ### 学习建议
  887. - 在 Chat 中发送"开始学习 {title}",导师会引导你学习
  888. - 遇到不理解的概念,随时追问
  889. - 完成学习后点击"完成课程"标记进度
  890. """,
  891. "practice": """
  892. ## 概述
  893. **{title}** — {description}
  894. ### 练习内容
  895. 这是一个实践课程,请在 Chat 中向导师请求练习任务。
  896. ### 完成标准
  897. - [ ] 理解练习要求
  898. - [ ] 独立完成代码实现
  899. - [ ] 验证代码正确运行
  900. - [ ] 与导师讨论你的实现方案
  901. ### 提示
  902. > 完成练习后,可以让导师 review 你的代码并提供改进建议。
  903. """,
  904. "quiz": """
  905. ## 概述
  906. **{title}** — {description}
  907. ### 测验说明
  908. 本课程包含知识测验,检验你对前面所学内容的理解。
  909. 请在 Chat 中让导师为你生成测验题目。
  910. ### 准备
  911. - 复习相关课程内容
  912. - 准备好回答概念题和代码题
  913. """,
  914. "project": """
  915. ## 概述
  916. **{title}** — {description}
  917. ### 项目要求
  918. 这是一个实战项目,综合运用所学知识完成一个完整的功能模块。
  919. 请在 Chat 中让导师为你分配项目任务并提供指导。
  920. ### 交付标准
  921. - [ ] 功能完整可用
  922. - [ ] 代码结构清晰
  923. - [ ] 包含错误处理
  924. - [ ] 有必要的注释
  925. """,
  926. }
  927. header = type_headers.get(lesson_type, "📖 学习内容")
  928. body = type_content.get(lesson_type, type_content["theory"])
  929. return f"""## {header}
  930. {body}
  931. """