| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259 |
- """
- 课程内容 - 为每个课程提供丰富的Markdown内容
- """
- from typing import Optional
- def get_lesson_content(lesson_id: str, title: str, lesson_type: str, description: str) -> str:
- """根据课程ID返回对应的Markdown内容"""
-
- # 优先查找特定课程的内容
- custom = _get_custom_content(lesson_id, title)
- if custom:
- return custom
-
- # 通用模板
- return _get_generic_content(title, description, lesson_type)
- def _get_custom_content(lesson_id: str, title: str) -> Optional[str]:
- """为特定课程ID返回个性化内容"""
-
- content_map = {
- # ======== 前端 - HTML/CSS ========
- "fe-html-01": """## 学习目标
- - 理解 HTML 文档的基本结构
- - 掌握 DOCTYPE、html、head、body 等核心标签
- - 了解 meta 标签的常见用法
- ## HTML 文档的基本结构
- 每个 HTML 文档都遵循一个基本的骨架结构:
- ```html
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>文档标题</title>
- </head>
- <body>
- <!-- 页面可见内容 -->
- <h1>Hello, World!</h1>
- <p>这是我的第一个网页。</p>
- </body>
- </html>
- ```
- ### 各部分作用
- | 标签 | 作用 |
- |------|------|
- | `<!DOCTYPE html>` | 声明文档类型为 HTML5 |
- | `<html>` | 文档的根元素,所有内容包含在内 |
- | `<head>` | 文档的元数据区(不可见) |
- | `<body>` | 文档的内容区(用户可见) |
- ### `<head>` 中的常用标签
- - **`<title>`** — 浏览器标签页显示的标题,对 SEO 也很重要
- - **`<meta charset="UTF-8">`** — 设置字符编码,避免乱码
- - **`<meta name="viewport">`** — 移动端适配声明
- - **`<link>`** — 引入外部 CSS 文件
- - **`<style>`** — 内嵌 CSS 样式
- ## 练习
- 创建一个包含以下内容的 HTML 文件:
- 1. 正确的文档结构声明
- 2. 设置标题为"我的第一个网页"
- 3. 在 body 中添加一个一级标题和一个段落
- > 💡 **提示**:使用 VS Code 新建 `.html` 文件后,输入 `!` 并按 Tab 可以快速生成 HTML5 骨架。
- """,
-
- "fe-html-02": """## 学习目标
- - 掌握常用 HTML 标签的语义和用法
- - 理解块级元素与行内元素的区别
- - 学会使用列表、图片、链接等构建内容
- ## 常用标签
- ### 文本标签
- ```html
- <!-- 标题 -->
- <h1>一级标题</h1>
- <h2>二级标题</h2>
- <h3>三级标题</h3>
- <!-- 段落与文本 -->
- <p>这是一个段落。</p>
- <strong>加重要内容</strong>
- <em>强调文本</em>
- <br> <!-- 换行 -->
- ```
- ### 列表
- ```html
- <!-- 无序列表 -->
- <ul>
- <li>苹果</li>
- <li>香蕉</li>
- <li>橘子</li>
- </ul>
- <!-- 有序列表 -->
- <ol>
- <li>第一步:打开编辑器</li>
- <li>第二步:编写代码</li>
- <li>第三步:保存文件</li>
- </ol>
- ```
- ### 链接与图片
- ```html
- <!-- 链接 -->
- <a href="https://example.com" target="_blank">打开示例网站</a>
- <!-- 图片 -->
- <img src="logo.png" alt="网站Logo" width="200">
- ```
- > ⚠️ **注意**:`<a>` 的 `target="_blank"` 会在新标签页打开链接。`<img>` 的 `alt` 属性用于图片加载失败时的替代文本,对无障碍访问很重要。
- ## 块级 vs 行内元素
- | 类别 | 特点 | 例子 |
- |------|------|------|
- | **块级元素** | 独占一行,可设置宽高 | `div`, `h1`-`h6`, `p`, `ul`, `ol` |
- | **行内元素** | 不换行,宽高由内容决定 | `span`, `a`, `strong`, `em`, `img` |
- ## 练习
- 创建一个"我的兴趣爱好"页面,包含:
- 1. 一个二级标题
- 2. 一段自我介绍
- 3. 一个无序列表列出你的兴趣(至少3项)
- 4. 一张图片和指向你最喜欢网站的外部链接
- """,
-
- "fe-css-01": """## 学习目标
- - 理解 CSS 的作用和基本语法
- - 掌握三种选择器:元素、类、ID
- - 了解选择器的优先级规则
- ## CSS 基本语法
- ```css
- 选择器 {
- 属性名: 属性值;
- 属性名: 属性值;
- }
- ```
- ### 引入 CSS 的方式
- **1. 外部样式表(推荐)**
- ```html
- <link rel="stylesheet" href="style.css">
- ```
- **2. 内部样式表**
- ```html
- <style>
- p {{ color: red; }}
- </style>
- ```
- **3. 行内样式(不推荐)**
- ```html
- <p style="color: red;">这段文字是红色</p>
- ```
- ## 三种基本选择器
- ### 元素选择器
- 选中所有该类型的标签:
- ```css
- p {{ color: #333; }}
- h1 {{ font-size: 24px; }}
- ```
- ### 类选择器(`.`)
- 选中所有带有该 class 的元素,可重复使用:
- ```css
- .highlight {{ background-color: yellow; }}
- .card {{ border: 1px solid #ccc; }}
- ```
- ```html
- <p class="highlight">这段有高亮背景</p>
- <div class="card">这是一个卡片</div>
- ```
- ### ID 选择器(`#`)
- **唯一**,一个页面中每个 ID 只能使用一次:
- ```css
- #header {{ height: 60px; }}
- #main-content {{ padding: 20px; }}
- ```
- ```html
- <div id="header">页面头部</div>
- ```
- ## 优先级(权重)
- 当多个选择器冲突时,按权重决定:
- | 选择器 | 权重 | 示例 |
- |--------|------|------|
- | 元素选择器 | 最低 | `p`、`h1` |
- | 类选择器 | 中等 | `.card`、`.highlight` |
- | ID选择器 | 最高 | `#header` |
- | 行内样式 | 更高 | `style="..."` |
- | `!important` | 最高(慎用) | `color: red !important` |
- > 🧪 **实验**:给同一个元素同时设置类和 ID 样式,观察哪个生效。
- ## 练习
- 创建一个 HTML 页面并添加 CSS:
- 1. 用元素选择器设置全局字体
- 2. 用类选择器创建两个不同颜色的卡片
- 3. 用 ID 选择器设置页面标题的样式
- """,
- "fe-css-02": """## 学习目标
- - 理解盒模型的四个组成部分
- - 掌握 width/height、padding、border、margin 的用法
- - 学会使用 `box-sizing` 控制盒模型行为
- ## 盒模型
- 每个 HTML 元素都可以看作一个"盒子",从内到外包含:
- ```
- ┌─────────────────────────────────┐
- │ Margin (外边距) │
- │ ┌───────────────────────────┐ │
- │ │ Border (边框) │ │
- │ │ ┌─────────────────────┐ │ │
- │ │ │ Padding (内边距) │ │ │
- │ │ │ ┌───────────────┐ │ │ │
- │ │ │ │ Content │ │ │ │
- │ │ │ │ (内容区域) │ │ │ │
- │ │ │ └───────────────┘ │ │ │
- │ │ └─────────────────────┘ │ │
- │ └───────────────────────────┘ │
- └─────────────────────────────────┘
- ```
- ### 代码示例
- ```css
- .box {{
- width: 200px;
- padding: 20px; /* 内容与边框之间的距离 */
- border: 2px solid #333; /* 边框 */
- margin: 10px; /* 盒子与其他元素的距离 */
- }}
- ```
- ### 盒模型的计算
- 默认情况下(`box-sizing: content-box`):
- **实际宽度 = width + padding × 2 + border × 2**
- 这意味着 `width: 200px` 加上 `padding: 20px` 和 `border: 2px` 后,实际占用的宽度是 **244px**!
- ### `box-sizing: border-box`
- 推荐做法——让 width 包含 padding 和 border:
- ```css
- * {{
- box-sizing: border-box;
- }}
- ```
- 这样 `width: 200px` 就是最终渲染宽度,padding 和 border 向内压缩。
- ## display 属性
- | 值 | 行为 |
- |----|------|
- | `block` | 块级,独占一行 |
- | `inline` | 行内,不换行 |
- | `inline-block` | 行内但可设宽高 |
- | `none` | 隐藏元素,不占空间 |
- ## 练习
- 用 HTML + CSS 实现下图效果(描述:三个卡片并排,每个卡片有标题、文字、边框和间距):
- 1. 三个 `div` 卡片横向排列
- 2. 每个卡片有 1px 边框、16px 内边距
- 3. 卡片之间用 margin 隔开
- 4. 使用 `box-sizing: border-box`
- """,
-
- "fe-css-03": """## 学习目标
- - 理解 Flexbox 的核心概念:主轴与交叉轴
- - 掌握容器属性和项目属性
- - 能使用 Flexbox 实现常见布局
- ## Flexbox 核心概念
- Flexbox 是一种一维布局模型,适合在**一行或一列**中排列元素。
- ```css
- .container {{
- display: flex; /* 开启 Flexbox */
- }}
- ```
- ### 主轴与交叉轴
- - **主轴(main axis)** — `flex-direction` 决定的方向
- - **交叉轴(cross axis)** — 与主轴垂直的方向
- ```
- flex-direction: row; → 主轴水平,从左到右
- flex-direction: column; → 主轴垂直,从上到下
- ```
- ## 容器属性
- ```css
- .container {{
- display: flex;
- flex-direction: row; /* row | column | row-reverse | column-reverse */
- justify-content: center; /* 主轴对齐方式 */
- align-items: center; /* 交叉轴对齐方式 */
- flex-wrap: wrap; /* 是否换行 */
- gap: 16px; /* 项目间距(推荐) */
- }}
- ```
- ### justify-content
- ```
- flex-start ┃ [项目1][项目2][项目3]
- center ┃ [项目1][项目2][项目3]
- space-between ┃ [项目1] [项目2] [项目3]
- space-around ┃ [项目1] [项目2] [项目3]
- ```
- ### align-items
- ```
- stretch ┃ 项目高度拉伸填满容器(默认)
- center ┃ 项目在交叉轴居中
- flex-start ┃ 项目在交叉轴起始位置
- ```
- ## 项目属性
- ```css
- .item {{
- flex: 1; /* 分配剩余空间的比例 */
- align-self: center; /* 单独对齐 */
- order: 2; /* 排列顺序(越小越前) */
- }}
- ```
- ## 常见布局示例
- ### 水平居中
- ```css
- .parent {{
- display: flex;
- justify-content: center;
- align-items: center;
- }}
- ```
- ### 两端对齐导航
- ```css
- .nav {{
- display: flex;
- justify-content: space-between;
- align-items: center;
- }}
- ```
- ### 响应式卡片网格
- ```css
- .grid {{
- display: flex;
- flex-wrap: wrap;
- gap: 20px;
- }}
- .card {{
- flex: 1 1 300px; /* 最小300px,自动换行 */
- }}
- ```
- ## 练习
- 用 Flexbox 实现一个导航栏:
- - 左侧是 Logo
- - 中间是导航链接(首页、关于、服务、联系)
- - 右侧是登录/注册按钮
- - 垂直居中
- """,
- # ======== 前端 - JavaScript ========
- "fe-js-01": """## 学习目标
- - 理解 `let`、`const`、`var` 的区别
- - 掌握 JavaScript 的基本数据类型
- - 了解引用类型与基本类型的差异
- ## 变量声明
- ### `let` vs `const` vs `var`
- | 关键字 | 可修改 | 作用域 | 推荐 |
- |--------|--------|--------|------|
- | `const` | ❌ 不可重新赋值 | 块级作用域 | **默认选择** |
- | `let` | ✅ 可重新赋值 | 块级作用域 | 需要改变时使用 |
- | `var` | ✅ 可重新赋值 | 函数作用域 | ❌ 避免使用 |
- ```javascript
- const PI = 3.14159;
- let count = 0;
- count = 1; // ✅ 可以
- // 常见错误
- const user = {{ name: 'Alice' }};
- user.name = 'Bob'; // ✅ const 对象的内容可以修改
- user = {{ name: 'Bob' }}; // ❌ 不能重新赋值
- ```
- ## 基本数据类型
- | 类型 | 示例 | 说明 |
- |------|------|------|
- | `number` | `42`, `3.14` | 整数和浮点数 |
- | `string` | `'hello'`, `"world"` | 文本 |
- | `boolean` | `true`, `false` | 布尔值 |
- | `null` | `null` | 空值 |
- | `undefined` | `undefined` | 未定义 |
- | `symbol` | `Symbol()` | 唯一标识符 |
- ```javascript
- const name = 'Alice';
- const age = 25;
- const isStudent = true;
- const score = null;
- let grade; // undefined
- // typeof 运算符
- console.log(typeof name); // "string"
- console.log(typeof age); // "number"
- ```
- ### 动态类型
- JavaScript 是动态类型语言,变量可以随时改变类型:
- ```javascript
- let value = 'hello';
- value = 42; // 变成了 number
- value = true; // 变成了 boolean
- ```
- ### 类型转换
- ```javascript
- // 隐式转换
- const result = '5' - 2; // 3 (字符串转数字)
- const msg = '结果是: ' + 42; // "结果是: 42"
- // 显式转换
- Number('42') // 42
- String(42) // "42"
- Boolean(0) // false
- Boolean('') // false
- Boolean('hello') // true
- ```
- > ⚠️ **常见陷阱**:`'5' + 2` 结果是 `'52'`(字符串拼接),而 `'5' - 2` 结果是 `3`(数值减法)。
- ## 引用类型
- 对象和数组是引用类型,赋值传递的是引用:
- ```javascript
- const a = {{ name: 'Alice' }};
- const b = a; // b 引用同一个对象
- b.name = 'Bob';
- console.log(a.name); // "Bob" — a 也被改了!
- ```
- ## 练习
- 1. 用 `const` 定义一个对象,包含你的姓名、年龄和爱好
- 2. 用 `let` 定义一个计数器,从 0 递增到 3
- 3. 分别使用 `typeof` 检查 `null`、`[]`、`{{}}` 的类型
- """,
- "fe-js-02": """## 学习目标
- - 掌握函数定义的多种方式
- - 理解作用域和闭包的概念
- - 了解箭头函数的特性
- ## 函数定义
- ### 函数声明 vs 函数表达式
- ```javascript
- // 函数声明(会被提升)
- function add(a, b) {{
- return a + b;
- }}
- // 函数表达式(不会被提升)
- const multiply = function(a, b) {{
- return a * b;
- }};
- ```
- ### 箭头函数
- ```javascript
- // 基本语法
- const add = (a, b) => a + b;
- const square = x => x * x; // 一个参数可省略括号
- const greet = () => 'Hello!';
- // 多行需要 {{}} 和 return
- const sum = (a, b) => {{
- const result = a + b;
- return result;
- }};
- ```
- ### 箭头函数 vs 普通函数
- | 区别 | 普通函数 | 箭头函数 |
- |------|----------|----------|
- | `this` | 动态绑定 | 继承外层作用域 |
- | `arguments` | 有 | 没有 |
- | 作为构造函数 | ✅ | ❌ |
- ## 作用域
- ```javascript
- const global = '全局变量';
- function outer() {{
- const outerVar = '外部函数变量';
-
- function inner() {{
- const innerVar = '内部函数变量';
- console.log(global); // ✅ 可访问
- console.log(outerVar); // ✅ 可访问
- }}
-
- console.log(innerVar); // ❌ 不可访问
- }}
- ```
- ## 闭包
- 函数 + 其被创建时所在的作用域环境的组合:
- ```javascript
- function createCounter() {{
- let count = 0;
- return function() {{
- count++;
- return count;
- }};
- }}
- const counter = createCounter();
- console.log(counter()); // 1
- console.log(counter()); // 2
- console.log(counter()); // 3
- ```
- > 💡 **用途**:数据私有化、函数工厂、模块模式
- ## 练习
- 1. 写一个箭头函数 `isEven(n)` 判断数字是否为偶数
- 2. 用闭包实现一个 `makeMultiplier(x)`,返回一个乘以 `x` 的函数
- 3. 比较普通函数和箭头函数中 `this` 的行为差异
- """,
- # ======== 前端 - Vue ========
- "fe-vue-01": """## 学习目标
- - 理解 Vue 3 的核心概念
- - 掌握 `ref` 和 `reactive` 响应式 API
- - 学会使用模板语法
- ## 什么是 Vue?
- Vue 是一个用于构建用户界面的**渐进式框架**。核心特性:
- - **声明式渲染** — 通过模板语法将数据绑定到 DOM
- - **响应式系统** — 数据变化自动更新视图
- - **组件化** — UI 拆分为独立的可复用组件
- ## 创建 Vue 应用
- ```javascript
- import {{ createApp, ref }} from 'vue'
- createApp({{
- setup() {{
- const count = ref(0)
- const increment = () => count.value++
-
- return {{ count, increment }}
- }}
- }}).mount('#app')
- ```
- ```html
- <div id="app">
- <p>计数: {{ "{{ count }}" }}</p>
- <button @click="increment">+1</button>
- </div>
- ```
- ## 响应式 API
- ### `ref` — 基本响应式
- ```javascript
- import {{ ref }} from 'vue'
- const count = ref(0)
- console.log(count.value) // 0
- count.value = 1
- ```
- > 在模板中使用时自动解包,不需要 `.value`
- ### `reactive` — 对象响应式
- ```javascript
- import {{ reactive }} from 'vue'
- const user = reactive({{
- name: 'Alice',
- age: 25
- }})
- user.age = 26 // 直接修改,无需 .value
- ```
- ### `computed` — 计算属性
- ```javascript
- import {{ ref, computed }} from 'vue'
- const price = ref(100)
- const quantity = ref(2)
- const total = computed(() => price.value * quantity.value)
- ```
- ## 模板语法
- ```html
- <!-- 文本插值 -->
- <p>{{ "{{ message }}" }}</p>
- <!-- 属性绑定 -->
- <img :src="imageUrl">
- <!-- 事件绑定 -->
- <button @click="handleClick">点击</button>
- <!-- 条件渲染 -->
- <p v-if="isVisible">可见</p>
- <!-- 列表渲染 -->
- <li v-for="(item, index) in items" :key="index">{{ "{{ item }}" }}</li>
- <!-- 双向绑定 -->
- <input v-model="username">
- ```
- ## 练习
- 创建一个简单的 Vue 应用:
- 1. 用 `ref` 定义用户名和年龄
- 2. 用 `computed` 计算是否成年(>=18)
- 3. 在模板中展示这些数据
- """,
- # ======== 后端 - Python ========
- "be-py-01": """## 学习目标
- - 回顾 Python 基础语法
- - 理解列表推导式、装饰器等进阶用法
- - 掌握 Python 常见最佳实践
- ## Python 基础回顾
- ```python
- # 变量与类型
- name: str = "Python"
- version: float = 3.11
- # 列表推导式
- squares = [x**2 for x in range(10) if x % 2 == 0]
- # 字典操作
- user = {{"name": "Alice", "age": 25}}
- print(user.get("name", "Unknown"))
- ```
- ## 装饰器
- 装饰器是一种在不修改原函数代码的情况下扩展其功能的方式:
- ```python
- from functools import wraps
- def log_calls(func):
- @wraps(func)
- def wrapper(*args, **kwargs):
- print(f"[LOG] 调用 {{func.__name__}}")
- result = func(*args, **kwargs)
- print(f"[LOG] {{func.__name__}} 返回 {{result}}")
- return result
- return wrapper
- @log_calls
- def add(a, b):
- return a + b
- add(3, 5)
- # [LOG] 调用 add
- # [LOG] add 返回 8
- ```
- ## 上下文管理器
- ```python
- # 使用 with 语句
- with open("file.txt", "r") as f:
- content = f.read()
- # 自定义上下文管理器
- from contextlib import contextmanager
- @contextmanager
- def timer():
- import time
- start = time.time()
- try:
- yield
- finally:
- elapsed = time.time() - start
- print(f"耗时: {{elapsed:.2f}}秒")
- with timer():
- sum(range(1000000))
- ```
- ## 类型提示
- ```python
- from typing import List, Optional, Dict
- def process_users(users: List[Dict[str, str]]) -> List[str]:
- \"\"\"提取所有用户名\"\"\"
- return [u.get("name", "") for u in users]
- def find_user(id: int) -> Optional[Dict[str, str]]:
- \"\"\"根据 ID 查找用户\"\"\"
- return None # 未找到
- ```
- ## 练习
- 1. 编写一个装饰器 `@retry(max_attempts=3)`,让函数在抛出异常时自动重试
- 2. 写一个上下文管理器,用于测量代码块的执行时间
- 3. 使用类型提示定义一个函数签名,处理用户列表数据
- """,
- "be-py-02": """## 学习目标
- - 理解文件读写的基本模式
- - 掌握异常处理的正确方式
- - 学会使用标准库处理常见任务
- ## 文件操作
- ```python
- # 推荐方式:使用 with 语句
- with open("data.txt", "r", encoding="utf-8") as f:
- content = f.read()
- # 逐行读取
- with open("data.txt", "r") as f:
- for line in f:
- print(line.strip())
- # 写入文件
- with open("output.txt", "w") as f:
- f.write("Hello, World!\\n")
- ```
- ## 异常处理
- ```python
- try:
- result = 10 / 0
- except ZeroDivisionError as e:
- print(f"不能除以零: {{e}}")
- except ValueError as e:
- print(f"值错误: {{e}}")
- except Exception as e:
- print(f"未知错误: {{e}}")
- else:
- print("没有发生异常")
- finally:
- print("总是执行")
- ```
- ### 自定义异常
- ```python
- class ValidationError(Exception):
- \"\"\"数据验证失败\"\"\"
- pass
- def validate_age(age: int):
- if age < 0 or age > 150:
- raise ValidationError(f"无效年龄: {{age}}")
- ```
- ## 标准库常用模块
- ```python
- import json
- import os
- import sys
- from datetime import datetime, timedelta
- # JSON 处理
- data = {{"name": "Alice", "age": 25}}
- json_str = json.dumps(data, ensure_ascii=False)
- parsed = json.loads(json_str)
- # 路径操作
- path = os.path.join("data", "subdir", "file.txt")
- print(os.path.exists(path))
- # 日期时间
- now = datetime.now()
- tomorrow = now + timedelta(days=1)
- print(now.strftime("%Y-%m-%d %H:%M:%S"))
- ```
- ## 练习
- 1. 读取一个 JSON 配置文件,解析其中的设置
- 2. 编写一个函数,安全地将字符串转换为整数,转换失败时返回 None
- 3. 使用 `os` 模块遍历一个目录下的所有 Python 文件
- 4. 使用 `datetime` 计算距离下个生日还有多少天
- """,
- # ======== 后端 - API ========
- "be-api-01": """## 学习目标
- - 理解 REST API 的核心原则
- - 掌握 HTTP 方法、状态码的正确使用
- - 学会设计资源导向的 URL
- ## REST 核心原则
- REST(Representational State Transfer)是一种 API 设计风格:
- 1. **资源导向** — URL 表示资源(名词),而不是操作(动词)
- 2. **HTTP 方法表示操作** — GET/ POST/ PUT/ DELETE
- 3. **无状态** — 每个请求包含所有必要信息
- 4. **统一接口** — 一致的 URL 模式和响应格式
- ## HTTP 方法
- | 方法 | 作用 | 幂等 | 请求体 |
- |------|------|------|--------|
- | GET | 获取资源 | ✅ | 通常无 |
- | POST | 创建资源 | ❌ | 有 |
- | PUT | 完整更新资源 | ✅ | 有 |
- | PATCH | 部分更新资源 | ❌ | 有 |
- | DELETE | 删除资源 | ✅ | 通常无 |
- ## 状态码
- | 状态码 | 含义 | 使用场景 |
- |--------|------|----------|
- | 200 OK | 请求成功 | GET、PUT 成功 |
- | 201 Created | 创建成功 | POST 创建资源 |
- | 204 No Content | 成功无返回体 | DELETE 成功 |
- | 400 Bad Request | 客户端请求错误 | 参数校验失败 |
- | 404 Not Found | 资源不存在 | 查询不存在的 ID |
- | 409 Conflict | 资源冲突 | 创建重复资源 |
- | 500 Internal Server Error | 服务器错误 | 未预期的异常 |
- ## URL 设计
- ```python
- # ✅ 好的设计(资源导向)
- GET /api/users # 获取用户列表
- GET /api/users/{{id}} # 获取单个用户
- POST /api/users # 创建用户
- PUT /api/users/{{id}} # 更新用户
- DELETE /api/users/{{id}} # 删除用户
- # ✅ 查询参数用于过滤/排序/分页
- GET /api/tasks?status=done&page=2&sort=created_at
- # ✅ 子资源
- GET /api/users/{{id}}/posts # 用户的文章列表
- # ❌ 不好的设计(动词在 URL 中)
- GET /api/getUser # ❌
- POST /api/createUser # ❌
- POST /api/deleteUser # ❌
- ```
- ## FastAPI 快速开始
- ```python
- from fastapi import FastAPI
- from pydantic import BaseModel
- app = FastAPI()
- class Item(BaseModel):
- name: str
- price: float
- @app.get("/items")
- async def list_items():
- return [{{"id": 1, "name": "Item 1", "price": 9.99}}]
- @app.post("/items")
- async def create_item(item: Item):
- return {{"id": 2, **item.model_dump()}}
- ```
- ## 练习
- 1. 为一个"博客系统"设计 RESTful API 端点(文章、评论、标签)
- 2. 说明每个端点的 HTTP 方法、URL、请求参数和响应状态码
- """,
- "be-api-02": """## 学习目标
- - 掌握 FastAPI 路由和参数处理
- - 理解请求体验证和响应模型
- - 学会使用依赖注入
- ## FastAPI 路由进阶
- ### 路径参数与查询参数
- ```python
- from fastapi import FastAPI, Query, Path
- app = FastAPI()
- @app.get("/users/{{user_id}}")
- async def get_user(
- user_id: int = Path(..., title="用户ID"),
- include_details: bool = Query(False, title="是否包含详情")
- ):
- return {{"user_id": user_id, "details": include_details}}
- ```
- ### 请求体验证
- ```python
- from pydantic import BaseModel, Field
- class CreateUserRequest(BaseModel):
- username: str = Field(..., min_length=3, max_length=50)
- email: str = Field(..., pattern=r"^[\\w.-]+@[\\w.-]+\\.\\w{{2,}}$")
- age: int = Field(ge=0, le=150)
- @app.post("/users")
- async def create_user(user: CreateUserRequest):
- return {{"message": "用户创建成功", "user": user}}
- ```
- ### 响应模型
- ```python
- from typing import List
- from pydantic import BaseModel
- class UserResponse(BaseModel):
- id: int
- username: str
- email: str
- @app.get("/users", response_model=List[UserResponse])
- async def list_users():
- return [
- UserResponse(id=1, username="alice", email="alice@example.com")
- ]
- ```
- ## 依赖注入
- ```python
- from fastapi import Depends, HTTPException
- def get_current_user(token: str = Query(...)):
- if token != "secret":
- raise HTTPException(status_code=401, detail="未授权")
- return {{"id": 1, "username": "alice"}}
- @app.get("/profile")
- async def get_profile(user: dict = Depends(get_current_user)):
- return user
- ```
- ## 错误处理
- ```python
- from fastapi import HTTPException
- from fastapi.responses import JSONResponse
- @app.get("/items/{{item_id}}")
- async def get_item(item_id: int):
- if item_id <= 0:
- raise HTTPException(
- status_code=400,
- detail="无效的项目ID"
- )
- # ... 查找项目
- return {{"id": item_id, "name": "Sample Item"}}
- ```
- ## 练习
- 1. 创建一个 Todo 的 CRUD API(使用内存列表存储)
- 2. 添加参数校验(标题非空、状态只能是 pending/done)
- 3. 使用响应模型控制返回字段
- """,
-
- # ======== 全栈 - Web基础 ========
- "fs-web-01": """## 学习目标
- - 理解 HTTP 协议的基本原理
- - 掌握请求-响应模型
- - 了解浏览器如何加载网页
- ## HTTP 协议
- HTTP(超文本传输协议)是 Web 的基础通信协议。
- ### 请求-响应模型
- ```
- 浏览器 服务器
- │ │
- ├── GET /index.html ──────────►│
- │ ├── 查找文件
- │◄── 200 OK + HTML 内容 ──────┤
- │ │
- ├── GET /style.css ───────────►│
- │◄── 200 OK + CSS 内容 ───────┤
- │ │
- ├── GET /app.js ──────────────►│
- │◄── 200 OK + JS 内容 ────────┤
- ```
- ### HTTP 请求结构
- ```
- GET /api/users HTTP/1.1
- Host: example.com
- Authorization: Bearer token123
- Content-Type: application/json
- {{"name": "Alice"}}
- ```
- ### HTTP 响应结构
- ```
- HTTP/1.1 200 OK
- Content-Type: application/json
- {{"id": 1, "name": "Alice"}}
- ```
- ## 常见请求头
- | 请求头 | 作用 |
- |--------|------|
- | `Authorization` | 认证信息 |
- | `Content-Type` | 请求体格式 |
- | `Accept` | 期望的响应格式 |
- | `User-Agent` | 客户端标识 |
- ## 常见响应头
- | 响应头 | 作用 |
- |--------|------|
- | `Content-Type` | 响应体格式 |
- | `Set-Cookie` | 设置 Cookie |
- | `Cache-Control` | 缓存策略 |
- | `Access-Control-Allow-Origin` | CORS 设置 |
- ## 浏览器加载流程
- 1. 解析 HTML → 构建 DOM 树
- 2. 加载 CSS → 构建 CSSOM 树
- 3. 合并为渲染树(Render Tree)
- 4. 布局(Layout)→ 计算位置和大小
- 5. 绘制(Paint)→ 渲染到屏幕
- > 💡 **关键**:CSS 会阻塞渲染,JavaScript 会阻塞解析。所以 `<script>` 标签通常放在 `</body>` 前。
- ## 练习
- 1. 用浏览器的开发者工具(F12)打开 Network 面板,访问一个网站,观察所有请求
- 2. 识别每个请求的类型(文档、样式、脚本、图片)
- 3. 查看一个 API 请求的请求头、响应头和响应体
- """,
- }
- # 检查是否有匹配的内容
- if lesson_id in content_map:
- return content_map[lesson_id]
-
- return None
- def _get_generic_content(title: str, description: str, lesson_type: str) -> str:
- """为没有个性化内容的课程生成通用内容"""
-
- type_headers = {
- "theory": "📖 理论学习",
- "practice": "💻 实践练习",
- "quiz": "❓ 知识测验",
- "project": "🚀 项目实战",
- }
-
- type_content = {
- "theory": """
- ## 概述
- **{title}** — {description}
- ### 学习要点
- 请跟随导师在对话中学习本课程的核心概念。导师将为你提供:
- 1. 详细的概念讲解和原理解析
- 2. 实际代码示例和最佳实践
- 3. 常见陷阱和注意事项
- ### 学习建议
- - 在 Chat 中发送"开始学习 {title}",导师会引导你学习
- - 遇到不理解的概念,随时追问
- - 完成学习后点击"完成课程"标记进度
- """,
- "practice": """
- ## 概述
- **{title}** — {description}
- ### 练习内容
- 这是一个实践课程,请在 Chat 中向导师请求练习任务。
- ### 完成标准
- - [ ] 理解练习要求
- - [ ] 独立完成代码实现
- - [ ] 验证代码正确运行
- - [ ] 与导师讨论你的实现方案
- ### 提示
- > 完成练习后,可以让导师 review 你的代码并提供改进建议。
- """,
- "quiz": """
- ## 概述
- **{title}** — {description}
- ### 测验说明
- 本课程包含知识测验,检验你对前面所学内容的理解。
- 请在 Chat 中让导师为你生成测验题目。
- ### 准备
- - 复习相关课程内容
- - 准备好回答概念题和代码题
- """,
- "project": """
- ## 概述
- **{title}** — {description}
- ### 项目要求
- 这是一个实战项目,综合运用所学知识完成一个完整的功能模块。
- 请在 Chat 中让导师为你分配项目任务并提供指导。
- ### 交付标准
- - [ ] 功能完整可用
- - [ ] 代码结构清晰
- - [ ] 包含错误处理
- - [ ] 有必要的注释
- """,
- }
-
- header = type_headers.get(lesson_type, "📖 学习内容")
- body = type_content.get(lesson_type, type_content["theory"])
-
- return f"""## {header}
- {body}
- """
|