diff --git a/金山办公作业/Week06/Outlet.md b/金山办公作业/Week06/Outlet.md
new file mode 100644
index 0000000..20cd0af
--- /dev/null
+++ b/金山办公作业/Week06/Outlet.md
@@ -0,0 +1,135 @@
+---
+tags: [frontend, react, react-router, routing, nested-routes]
+create time: 2026-04-25 15:30
+---
+
+# Outlet:嵌套路由的出口 / 占位符
+
+## 概述
+
+`Outlet` 是 React Router 中用于"嵌套路由占位"的组件,负责在父组件布局中预留一个位置,由子路由匹配到的组件来渲染。
+
+## 正文
+
+### 为什么要用 Outlet
+
+假设有这样的路由结构:
+
+- `/dashboard`
+- `/courses`
+- `/students`
+
+它们都共享同一个外层布局——左侧导航栏、顶部标题栏、主内容区域。如果不使用 `Outlet`,每个页面组件都要重复写一遍布局结构。
+
+有了 `Outlet`,可以把公共布局抽到一个**父路由组件**中,子页面内容自动渲染到 `Outlet` 位置,不需要重复代码。
+
+> 💡 **想一想**:如果每个子页面都自己写侧边栏和顶栏,当侧边栏需要修改时,需要改几个文件?用了 `Outlet` 后又需要改几个?
+
+### 路由结构对比
+
+```mermaid
+graph TB
+ subgraph "不使用 Outlet"
+ A1[LoginPage] --> B1[浏览器]
+ A2[DashboardPage] --> B1
+ A3[CoursesPage] --> B1
+ A4[StudentsPage] --> B1
+ end
+
+ subgraph "使用 Outlet"
+ Layout[Layout 父组件
header + aside + Outlet] --> B2[浏览器]
+ subgraph "Layout 内部"
+ H[]
+ S[
+```
+
+### 建议安装(按需)
+
+| 包名 | 作用 | 一句话理解 |
+|------|------|-----------|
+| `react-router-dom` | React 路由,多页面切换 | 各个房间之间的通道 |
+| `axios` | HTTP 请求库 | 跟后端通信的电话线 |
+| `zustand` | 轻量级状态管理 | 全局状态(登录用户、主题等) |
+
+```tsx
+// react-router-dom 示例:定义路由
+import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+
+const router = createBrowserRouter([
+ { path: '/login', element: },
+ { path: '/dashboard', element: },
+ { path: '/courses', element: },
+])
+```
+
+```ts
+// axios 示例:封装请求
+import axios from 'axios'
+
+const request = axios.create({
+ baseURL: '/api',
+ timeout: 10000,
+})
+
+// 统一处理 token 和错误
+request.interceptors.request.use((config) => {
+ const token = localStorage.getItem('token')
+ if (token) config.headers.Authorization = `Bearer ${token}`
+ return config
+})
+```
+
+### 安装顺序(适合初学者)
+
+```bash
+# 第一步:创建项目
+npm create vite@latest client -- --template react-ts
+cd client
+npm install
+
+# 第二步:安装 UI 组件库
+npm install antd
+
+# 第三步:安装路由和请求
+npm install react-router-dom axios
+
+# 第四步:安装 Tailwind CSS(需要额外配置)
+npm install -D tailwindcss postcss autoprefixer
+npx tailwindcss init -p
+
+# 第五步:安装开发类型声明(如果需要)
+npm install -D @types/react @types/react-dom
+```
+
+### 项目依赖全景图
+
+你可以把这些依赖理解为"盖房子"的过程:
+
+```mermaid
+graph LR
+ subgraph "基础设施"
+ V[Vite - 施工队]
+ end
+ subgraph "主体结构"
+ R[React - 房子骨架]
+ RDOM[React-DOM - 落地到浏览器]
+ end
+ subgraph "标准与规范"
+ TS[TypeScript - 图纸标准]
+ end
+ subgraph "装修材料"
+ ANT[Ant Design - 现成组件]
+ TW[Tailwind CSS - 装修工具]
+ end
+ subgraph "配套工程"
+ RR[React Router - 房间通道]
+ AX[Axios - 通信线路]
+ end
+
+ V --> R
+ R --> RDOM
+ TS -.-> R
+ TS -.-> RDOM
+ ANT -.-> R
+ TW -.-> R
+ RR -.-> R
+ AX -.-> R
+```
+
+### 依赖关系总结
+
+| 类别 | 必装 | 建议 | 暂不装 |
+|------|------|------|--------|
+| 框架 | `react`, `react-dom` | - | - |
+| 构建 | `vite` | - | - |
+| 类型 | `typescript` | - | - |
+| UI | `antd` | - | - |
+| 样式 | `tailwindcss` | - | - |
+| 路由 | - | `react-router-dom` | - |
+| 请求 | - | `axios` | - |
+| 状态管理 | - | `zustand` | - |
+
+## 关联笔记
+
+- [[登录安全流程]]
+- [[验收任务清单]]
+- [[题目-在线管理平台]]
diff --git a/金山办公作业/Week06/统一封装请求.md b/金山办公作业/Week06/统一封装请求.md
new file mode 100644
index 0000000..c2c3de8
--- /dev/null
+++ b/金山办公作业/Week06/统一封装请求.md
@@ -0,0 +1,209 @@
+---
+tags: [frontend, api, typescript, fetch, abstraction]
+create time: 2026-04-25 14:30
+---
+
+# 统一封装请求:apiRequest 函数
+
+## 概述
+
+把前端所有接口调用中**重复的逻辑**抽到一个公共函数里,让每个页面只需要关心「调哪个接口、传什么参数」。
+
+> 💡 **想一想**:如果每个页面都自己写一遍 token 拼接、错误处理、JSON 解析,代码会变得怎样?
+
+答案是——重复、易错、难维护。所以业界的标准做法就是:**抽出一个通用请求函数**。
+
+---
+
+## 核心代码
+
+```ts
+export async function apiRequest(path: string, init?: RequestInit): Promise {
+ function getAuthToken() {
+ return window.localStorage.getItem(TOKEN_STORAGE_KEY) ?? ''
+ }
+
+ const response = await fetch(`${API_BASE}${path}`, {
+ ...init,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...(getAuthToken() ? { Authorization: `Bearer ${getAuthToken()}` } : {}),
+ ...(init?.headers ?? {}),
+ },
+ })
+
+ const result = (await response.json()) as ApiResponse
+
+ if (!response.ok || result.code !== 200) {
+ throw new Error(result.msg || '请求失败')
+ }
+
+ return result.data
+}
+```
+
+---
+
+## 逐行拆解:这段代码在做什么
+
+### 1. 泛型 `` — 让调用方决定返回值类型
+
+```ts
+export async function apiRequest(path: string, init?: RequestInit): Promise
+```
+
+- `path`:接口路径,比如 `'/users'`
+- `init`:fetch 配置项,比如 `method`、`body`
+- ``:返回值类型由调用方指定
+
+**好处**:调用时可以自动获得类型提示和类型检查。
+
+### 2. 自动读取 token
+
+```ts
+function getAuthToken() {
+ return window.localStorage.getItem(TOKEN_STORAGE_KEY) ?? ''
+}
+```
+
+从本地存储取出登录凭证。有 token 就返回 token,没有就返回空字符串。
+
+### 3. 拼接完整请求地址
+
+```ts
+const response = await fetch(`${API_BASE}${path}`, { ... })
+```
+
+把基础地址和接口路径拼在一起:
+
+| 变量 | 值 |
+|------|-----|
+| `API_BASE` | `'http://localhost:3000/api'` |
+| `path` | `'/login'` |
+| **最终 URL** | `'http://localhost:3000/api/login'` |
+
+### 4. 合并请求配置(重点)
+
+```ts
+{
+ ...init, // 外部传的配置
+ headers: {
+ 'Content-Type': 'application/json', // 统一 JSON 格式
+ ...(getAuthToken() ? { Authorization: `Bearer ${getAuthToken()}` } : {}), // 自动加 token
+ ...(init?.headers ?? {}), // 合并外部请求头
+ },
+}
+```
+
+层层展开,体现一个设计思想:**统一封装但允许扩展**。
+
+| 优先级 | 顺序 | 说明 |
+|--------|------|------|
+| 1 | 最低 | `'Content-Type'` 统一设为 JSON |
+| 2 | 中间 | 有 token 就自动带上 `Authorization` |
+| 3 | 最高 | 调用方自定义的请求头可以覆盖 |
+
+### 5. 统一解析响应
+
+```ts
+const result = (await response.json()) as ApiResponse
+```
+
+默认后端返回格式为:
+
+```json
+{
+ "code": 200,
+ "msg": "success",
+ "data": { ... }
+}
+```
+
+### 6. 统一判断成功失败
+
+```ts
+if (!response.ok || result.code !== 200) {
+ throw new Error(result.msg || '请求失败')
+}
+```
+
+做了双重判断:
+
+- **HTTP 层面**:`response.ok` 检查状态码是否在 200~299
+- **业务层面**:`result.code === 200` 检查后端返回的业务状态
+
+任意一个失败就抛错,页面层不用再写重复的判断逻辑。
+
+### 7. 只返回业务数据
+
+```ts
+return result.data
+```
+
+最终直接返回 `data` 字段,调用方拿到的就是最干净的数据。
+
+---
+
+## 请求流程
+
+```mermaid
+flowchart LR
+ A[调用 apiRequest] --> B[读取本地 token]
+ B --> C[拼接完整 URL]
+ C --> D[合并请求配置和请求头]
+ D --> E[发起 fetch 请求]
+ E --> F[解析 JSON 响应]
+ F --> G{是否成功?}
+ G -->|HTTP 或 code 异常| H[抛出错误]
+ G -->|都正常| I[返回 data]
+ H --> J[页面层捕获错误]
+ I --> K[页面层处理业务数据]
+```
+
+---
+
+## 实际调用示例
+
+获取课程列表:
+
+```ts
+const courses = await apiRequest('/courses')
+```
+
+提交表单:
+
+```ts
+const user = await apiRequest('/login', {
+ method: 'POST',
+ body: JSON.stringify({ username, password }),
+})
+```
+
+调用方不需要关心:
+
+- token 怎么加
+- JSON 怎么解析
+- 错误怎么处理
+
+---
+
+## 总结:这段封装的本质
+
+> 把**「请求的共性」**抽出来,变成标准入口;
+> 把**「接口的差异」**保留给调用参数。
+
+具体体现在四个层面:
+
+| 层面 | 封装内容 |
+|------|----------|
+| 函数抽象 | `apiRequest` 统一入口 |
+| 配置合并 | headers、URL 自动拼接 |
+| 错误统一处理 | HTTP 状态 + 业务 code 双重判断 |
+| 返回值格式化 | 只返回 `data`,屏蔽外围结构 |
+
+---
+
+## 关联笔记
+
+- [[路由原理]]
+- [[前端项目依赖清单]]
diff --git a/金山办公作业/Week06/路由原理.md b/金山办公作业/Week06/路由原理.md
new file mode 100644
index 0000000..ac4986b
--- /dev/null
+++ b/金山办公作业/Week06/路由原理.md
@@ -0,0 +1,113 @@
+---
+tags: [frontend, react, react-router, routing, spa]
+create time: 2026-04-25 15:30
+---
+
+# 路由原理:BrowserRouter 与组件协作
+
+## 概述
+
+本文梳理 React Router 的核心组件如何配合完成单页应用(SPA)的路由跳转。重点理解 `` 作为"路由引擎"的作用,以及 `NavLink`、`Routes`、`Route`、`Navigate` 等组件的职责分工。
+
+---
+
+## 正文
+
+### `` 的核心作用
+
+`` 就是 React Router 的**"总开关"和"运行环境"**,没有它,路由组件无法正常工作。
+
+```tsx
+
+
+
+```
+
+它做三件事:
+
+1. **提供路由上下文** — 让 `Routes`、`Route`、`NavLink` 知道当前路径是什么、该显示哪个页面
+2. **无刷新切换页面** — 基于浏览器的 `History API`,URL 变了但整页不会刷新
+3. **全局可用** — 因为它包住了 ``,其所有子组件都能使用路由能力
+
+> 💡 **想一想**:为什么 `` 必须包裹 `` 而不是只包某个子组件?
+>
+> 如果它只包了 `` 但没有包 ``,点击导航按钮会报错:
+>
+> ```
+> Uncaught Error: useHref() may be used only in the context of a component
+> ```
+>
+> 因为 `NavLink` 内部通过 React Context 读取路由数据,如果它处于 `` 之外,就**读不到任何路由信息**,只能直接崩溃。
+
+### 组件职责类比
+
+| 组件 | 类比角色 | 一句话说明 |
+|------|---------|-----------|
+| `` | 交通系统 | 提供整个路由的运行环境 |
+| `NavLink` | 路牌 / 入口 | 用户点击后触发路径切换 |
+| `Routes` | 调度中心 | 读取当前路径,决定走哪条路 |
+| `Route` | 目的地 | 定义"路径 → 页面"的映射 |
+| `Navigate` | 自动转弯 | 把用户重定向到另一个路径 |
+
+### 路由流程
+
+当用户点击左侧导航栏的"课程管理"时,背后发生了什么?
+
+```mermaid
+flowchart LR
+ A[用户点击 NavLink] --> B[URL 变为 /courses]
+ B --> C[Routes 读取当前路径]
+ C --> D{匹配哪个 Route?}
+ D -->|path=/courses| E[渲染 CoursesPage]
+ D -->|无匹配| F[不显示任何页面]
+ E --> G[页面切换完成,整页未刷新]
+```
+
+逐帧拆解:
+
+1. `NavLink to="/courses"` 将浏览器地址变为 `/courses`
+2. `Routes` 读取当前路径
+3. 匹配到 `} />`
+4. `CoursesPage` 组件渲染
+
+整个过程**地址栏变了、组件切换了、但页面没有刷新**。
+
+### 实际代码中的用法
+
+**路由声明**(`App.tsx`):
+
+```tsx
+// 根路径自动跳转到 dashboard(replace 不留后退痕迹)
+} />
+
+// 正常路由映射
+} />
+} />
+```
+
+**导航链接**:
+
+```tsx
+课程管理
+```
+
+**解读**:`} />` 表示当用户访问根路径 `/` 时,自动跳转到 `/dashboard`。`replace` 参数会让浏览器用新路径替换当前历史记录,这样用户按"后退"按钮不会回到登录页。
+
+### 为什么不能去掉 ``?
+
+路由组件需要"上下文"才知道当前路径是什么、该往哪里跳。如果去掉 ``:
+
+- `NavLink` 不知道点击后该跳到哪里
+- `Route` / `Routes` 不知道当前路径是什么
+- `Navigate` 无法执行跳转
+
+它们会直接报错。
+
+> 💡 **想一想**:如果我们不用 ``,还有哪些方式能让路由组件知道当前路径?(提示:URL 地址栏本身就是公开的,React Router 还提供了 `HashRouter` 和 `MemoryRouter`,它们分别适用于什么场景?)
+
+---
+
+## 关联笔记
+
+- [[金山办公作业/Week06/登录安全流程]] - 用户认证与 JWT Token
+- [[Outlet]] - 嵌套路由的出口 / 占位符
diff --git a/金山办公作业/Week06/题目.md b/金山办公作业/Week06/题目-在线管理平台.md
similarity index 98%
rename from 金山办公作业/Week06/题目.md
rename to 金山办公作业/Week06/题目-在线管理平台.md
index 191226f..d3ccb27 100644
--- a/金山办公作业/Week06/题目.md
+++ b/金山办公作业/Week06/题目-在线管理平台.md
@@ -6,6 +6,8 @@
本作业要求实现一个在线学习管理平台的部分内容,涵盖前端与后端两部分。前端基于 React + TypeScript 技术栈构建,后端采用 Koa 开发。系统实现了用户登录认证、工作台数据可视化、课程管理、学生管理及学习总结展示等功能,支持数据的增删改查等操作。
+**相关技术参考**:[[登录安全流程]]、[[路由原理]]
+
# 二、功能需求
### 1. 登录认证
@@ -57,6 +59,9 @@
### 前端
技术栈:Vite、React、TypeScript、Ant Design、Tailwind CSS 等(禁止使用第三方脚手架如 UmiJS 、飞冰、Ant Design Pro 等同类集成方案)。
+参考 ->
+ 1. [[前端项目依赖清单]]
+ 2. [[统一封装请求]]
### 后端
diff --git a/金山办公作业/Week06/验收任务清单.md b/金山办公作业/Week06/验收任务清单.md
index f5edc13..9f39477 100644
--- a/金山办公作业/Week06/验收任务清单.md
+++ b/金山办公作业/Week06/验收任务清单.md
@@ -1,6 +1,6 @@
# 验收任务清单
-> 来源:[[题目]]
+> 来源:[[题目-在线管理平台]]
## 一、前端功能验收