learning_content.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. from typing import List, Dict, Optional
  2. from ..models.learning import (
  3. LearningPath, LearningPathData, LearningModule, LearningLesson, ModuleStatus
  4. )
  5. def get_frontend_path() -> LearningPathData:
  6. return LearningPathData(
  7. path=LearningPath.FRONTEND,
  8. title="前端开发",
  9. description="从HTML/CSS基础到现代前端框架",
  10. icon="🎨",
  11. modules=[
  12. LearningModule(
  13. id="fe-html-css",
  14. title="HTML & CSS 基础",
  15. description="网页结构与样式入门",
  16. icon="📝",
  17. order=1,
  18. status=ModuleStatus.NOT_STARTED,
  19. lessons=[
  20. LearningLesson(
  21. id="fe-html-01",
  22. title="HTML文档结构",
  23. description="DOCTYPE、head、body标签",
  24. type="theory",
  25. duration_minutes=15
  26. ),
  27. LearningLesson(
  28. id="fe-html-02",
  29. title="常用HTML标签",
  30. description="标题、段落、链接、图片、列表",
  31. type="theory",
  32. duration_minutes=20
  33. ),
  34. LearningLesson(
  35. id="fe-css-01",
  36. title="CSS选择器",
  37. description="元素、类、ID、属性选择器",
  38. type="theory",
  39. duration_minutes=20
  40. ),
  41. LearningLesson(
  42. id="fe-css-02",
  43. title="盒模型与布局",
  44. description="margin、padding、border、display",
  45. type="practice",
  46. duration_minutes=30
  47. ),
  48. LearningLesson(
  49. id="fe-css-03",
  50. title="Flexbox布局",
  51. description="弹性盒子布局完全指南",
  52. type="practice",
  53. duration_minutes=40
  54. ),
  55. ]
  56. ),
  57. LearningModule(
  58. id="fe-javascript",
  59. title="JavaScript 核心",
  60. description="JavaScript语言基础",
  61. icon="⚡",
  62. order=2,
  63. status=ModuleStatus.LOCKED,
  64. lessons=[
  65. LearningLesson(
  66. id="fe-js-01",
  67. title="变量与数据类型",
  68. description="let、const、基本类型与引用类型",
  69. type="theory",
  70. duration_minutes=25
  71. ),
  72. LearningLesson(
  73. id="fe-js-02",
  74. title="函数与作用域",
  75. description="函数声明、箭头函数、闭包",
  76. type="theory",
  77. duration_minutes=30
  78. ),
  79. LearningLesson(
  80. id="fe-js-03",
  81. title="DOM操作",
  82. description="查询、修改、创建DOM元素",
  83. type="practice",
  84. duration_minutes=40
  85. ),
  86. LearningLesson(
  87. id="fe-js-04",
  88. title="事件处理",
  89. description="事件监听、事件委托、事件对象",
  90. type="practice",
  91. duration_minutes=35
  92. ),
  93. ]
  94. ),
  95. LearningModule(
  96. id="fe-vue",
  97. title="Vue.js 框架",
  98. description="现代Vue 3开发",
  99. icon="💚",
  100. order=3,
  101. status=ModuleStatus.LOCKED,
  102. lessons=[
  103. LearningLesson(
  104. id="fe-vue-01",
  105. title="Vue 3 基础",
  106. description="模板语法、响应式数据、computed",
  107. type="theory",
  108. duration_minutes=30
  109. ),
  110. LearningLesson(
  111. id="fe-vue-02",
  112. title="组件系统",
  113. description="组件创建、props、events、slots",
  114. type="theory",
  115. duration_minutes=35
  116. ),
  117. LearningLesson(
  118. id="fe-vue-03",
  119. title="组合式API",
  120. description="setup、ref、reactive、生命周期",
  121. type="practice",
  122. duration_minutes=40
  123. ),
  124. LearningLesson(
  125. id="fe-vue-04",
  126. title="状态管理",
  127. description="Pinia状态管理实践",
  128. type="practice",
  129. duration_minutes=30
  130. ),
  131. ]
  132. ),
  133. LearningModule(
  134. id="fe-project",
  135. title="实战项目",
  136. description="构建完整的前端应用",
  137. icon="🚀",
  138. order=4,
  139. status=ModuleStatus.LOCKED,
  140. lessons=[
  141. LearningLesson(
  142. id="fe-proj-01",
  143. title="项目规划",
  144. description="需求分析、技术选型、架构设计",
  145. type="theory",
  146. duration_minutes=30
  147. ),
  148. LearningLesson(
  149. id="fe-proj-02",
  150. title="核心功能开发",
  151. description="实现主要功能模块",
  152. type="project",
  153. duration_minutes=120
  154. ),
  155. LearningLesson(
  156. id="fe-proj-03",
  157. title="优化与部署",
  158. description="性能优化、构建部署",
  159. type="project",
  160. duration_minutes=60
  161. ),
  162. ]
  163. ),
  164. ]
  165. )
  166. def get_backend_path() -> LearningPathData:
  167. return LearningPathData(
  168. path=LearningPath.BACKEND,
  169. title="后端开发",
  170. description="Python后端开发与API设计",
  171. icon="⚙️",
  172. modules=[
  173. LearningModule(
  174. id="be-python",
  175. title="Python 基础",
  176. description="Python语言核心",
  177. icon="🐍",
  178. order=1,
  179. status=ModuleStatus.NOT_STARTED,
  180. lessons=[
  181. LearningLesson(
  182. id="be-py-01",
  183. title="Python语法基础",
  184. description="变量、类型、运算符",
  185. type="theory",
  186. duration_minutes=20
  187. ),
  188. LearningLesson(
  189. id="be-py-02",
  190. title="控制流与函数",
  191. description="条件、循环、函数定义",
  192. type="theory",
  193. duration_minutes=25
  194. ),
  195. LearningLesson(
  196. id="be-py-03",
  197. title="面向对象编程",
  198. description="类、继承、多态",
  199. type="theory",
  200. duration_minutes=30
  201. ),
  202. LearningLesson(
  203. id="be-py-04",
  204. title="异常处理与文件操作",
  205. description="try/except、文件读写",
  206. type="practice",
  207. duration_minutes=25
  208. ),
  209. ]
  210. ),
  211. LearningModule(
  212. id="be-api",
  213. title="REST API 设计",
  214. description="FastAPI构建RESTful服务",
  215. icon="🔌",
  216. order=2,
  217. status=ModuleStatus.LOCKED,
  218. lessons=[
  219. LearningLesson(
  220. id="be-api-01",
  221. title="HTTP协议基础",
  222. description="请求方法、状态码、头部",
  223. type="theory",
  224. duration_minutes=20
  225. ),
  226. LearningLesson(
  227. id="be-api-02",
  228. title="FastAPI入门",
  229. description="路由、请求、响应",
  230. type="theory",
  231. duration_minutes=30
  232. ),
  233. LearningLesson(
  234. id="be-api-03",
  235. title="数据验证",
  236. description="Pydantic模型、请求验证",
  237. type="practice",
  238. duration_minutes=35
  239. ),
  240. LearningLesson(
  241. id="be-api-04",
  242. title="数据库集成",
  243. description="SQLAlchemy、数据库操作",
  244. type="practice",
  245. duration_minutes=45
  246. ),
  247. ]
  248. ),
  249. LearningModule(
  250. id="be-system",
  251. title="系统设计",
  252. description="架构设计与最佳实践",
  253. icon="🏗️",
  254. order=3,
  255. status=ModuleStatus.LOCKED,
  256. lessons=[
  257. LearningLesson(
  258. id="be-sys-01",
  259. title="设计模式",
  260. description="常用设计模式与应用场景",
  261. type="theory",
  262. duration_minutes=40
  263. ),
  264. LearningLesson(
  265. id="be-sys-02",
  266. title="性能优化",
  267. description="缓存、异步、并发",
  268. type="theory",
  269. duration_minutes=35
  270. ),
  271. LearningLesson(
  272. id="be-sys-03",
  273. title="安全实践",
  274. description="认证、授权、数据安全",
  275. type="practice",
  276. duration_minutes=30
  277. ),
  278. ]
  279. ),
  280. LearningModule(
  281. id="be-project",
  282. title="实战项目",
  283. description="构建完整的后端服务",
  284. icon="🚀",
  285. order=4,
  286. status=ModuleStatus.LOCKED,
  287. lessons=[
  288. LearningLesson(
  289. id="be-proj-01",
  290. title="项目架构",
  291. description="目录结构、配置管理",
  292. type="theory",
  293. duration_minutes=25
  294. ),
  295. LearningLesson(
  296. id="be-proj-02",
  297. title="核心功能实现",
  298. description="业务逻辑开发",
  299. type="project",
  300. duration_minutes=120
  301. ),
  302. LearningLesson(
  303. id="be-proj-03",
  304. title="测试与部署",
  305. description="单元测试、集成测试、部署",
  306. type="project",
  307. duration_minutes=60
  308. ),
  309. ]
  310. ),
  311. ]
  312. )
  313. def get_fullstack_path() -> LearningPathData:
  314. return LearningPathData(
  315. path=LearningPath.FULLSTACK,
  316. title="全栈开发",
  317. description="前端+后端全栈技能",
  318. icon="🌐",
  319. modules=[
  320. LearningModule(
  321. id="fs-web-basics",
  322. title="Web基础",
  323. description="HTML/CSS/JS核心",
  324. icon="🌍",
  325. order=1,
  326. status=ModuleStatus.NOT_STARTED,
  327. lessons=[
  328. LearningLesson(
  329. id="fs-web-01",
  330. title="HTML/CSS基础",
  331. description="网页结构与样式",
  332. type="theory",
  333. duration_minutes=25
  334. ),
  335. LearningLesson(
  336. id="fs-web-02",
  337. title="JavaScript基础",
  338. description="JS核心概念",
  339. type="theory",
  340. duration_minutes=30
  341. ),
  342. LearningLesson(
  343. id="fs-web-03",
  344. title="DOM与事件",
  345. description="页面交互实现",
  346. type="practice",
  347. duration_minutes=35
  348. ),
  349. ]
  350. ),
  351. LearningModule(
  352. id="fs-frontend",
  353. title="前端框架",
  354. description="Vue.js开发",
  355. icon="💚",
  356. order=2,
  357. status=ModuleStatus.LOCKED,
  358. lessons=[
  359. LearningLesson(
  360. id="fs-fe-01",
  361. title="Vue 3基础",
  362. description="组件、响应式、生命周期",
  363. type="theory",
  364. duration_minutes=30
  365. ),
  366. LearningLesson(
  367. id="fs-fe-02",
  368. title="路由与状态",
  369. description="Vue Router、Pinia",
  370. type="practice",
  371. duration_minutes=40
  372. ),
  373. ]
  374. ),
  375. LearningModule(
  376. id="fs-backend",
  377. title="后端开发",
  378. description="Python + FastAPI",
  379. icon="⚙️",
  380. order=3,
  381. status=ModuleStatus.LOCKED,
  382. lessons=[
  383. LearningLesson(
  384. id="fs-be-01",
  385. title="Python基础",
  386. description="语法、OOP、异常处理",
  387. type="theory",
  388. duration_minutes=30
  389. ),
  390. LearningLesson(
  391. id="fs-be-02",
  392. title="FastAPI开发",
  393. description="路由、验证、数据库",
  394. type="practice",
  395. duration_minutes=45
  396. ),
  397. ]
  398. ),
  399. LearningModule(
  400. id="fs-fullstack",
  401. title="全栈实战",
  402. description="构建完整应用",
  403. icon="🚀",
  404. order=4,
  405. status=ModuleStatus.LOCKED,
  406. lessons=[
  407. LearningLesson(
  408. id="fs-fs-01",
  409. title="前后端联调",
  410. description="API对接、数据流",
  411. type="practice",
  412. duration_minutes=60
  413. ),
  414. LearningLesson(
  415. id="fs-fs-02",
  416. title="部署上线",
  417. description="构建、部署、监控",
  418. type="project",
  419. duration_minutes=60
  420. ),
  421. ]
  422. ),
  423. ]
  424. )
  425. def _inject_lesson_content(path_data: LearningPathData):
  426. """为路径中的所有课程注入Markdown内容"""
  427. from .lesson_content import get_lesson_content
  428. for module in path_data.modules:
  429. for lesson in module.lessons:
  430. if not lesson.content_markdown:
  431. lesson.content_markdown = get_lesson_content(
  432. lesson.id, lesson.title, lesson.type, lesson.description
  433. )
  434. def get_learning_path(path: LearningPath) -> LearningPathData:
  435. if path == LearningPath.FRONTEND:
  436. data = get_frontend_path()
  437. elif path == LearningPath.BACKEND:
  438. data = get_backend_path()
  439. else:
  440. data = get_fullstack_path()
  441. _inject_lesson_content(data)
  442. return data
  443. def get_all_paths() -> List[LearningPathData]:
  444. paths = [
  445. get_frontend_path(),
  446. get_backend_path(),
  447. get_fullstack_path()
  448. ]
  449. for p in paths:
  450. _inject_lesson_content(p)
  451. return paths
  452. def find_next_lesson(path_type: str, current_lesson_id: str, completed_lessons: List[str]) -> Optional[Dict]:
  453. """根据当前课程,找到路径中下一个未完成的课程
  454. Args:
  455. path_type: 路径类型 ('frontend' / 'backend' / 'fullstack')
  456. current_lesson_id: 当前课程的 lesson_id
  457. completed_lessons: 已完成的 lesson_id 列表
  458. Returns:
  459. 下一个课程的 {title, description, id} 或 None
  460. """
  461. try:
  462. path_enum = LearningPath(path_type)
  463. path_data = get_learning_path(path_enum)
  464. except Exception:
  465. return None
  466. # 扁平化所有课程(保持顺序)
  467. all_lessons: List[Dict] = []
  468. for module in path_data.modules:
  469. for lesson in module.lessons:
  470. all_lessons.append({
  471. "id": lesson.id,
  472. "title": lesson.title,
  473. "description": lesson.description,
  474. "module_title": module.title,
  475. "module_id": module.id,
  476. })
  477. # 找到当前课程在列表中的位置
  478. current_idx = None
  479. for i, l in enumerate(all_lessons):
  480. if l["id"] == current_lesson_id:
  481. current_idx = i
  482. break
  483. if current_idx is None:
  484. return None
  485. # 从当前课程之后找第一个未完成的
  486. for i in range(current_idx + 1, len(all_lessons)):
  487. if all_lessons[i]["id"] not in completed_lessons:
  488. return all_lessons[i]
  489. return None