knowledge.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. """知识点路由"""
  2. from fastapi import APIRouter, Request, Query, Depends
  3. from app.database import get_connection, get_knowledge_tree, search_knowledge
  4. from app.routers.auth import verify_token
  5. router = APIRouter()
  6. @router.get("/knowledge/tree")
  7. def knowledge_tree(request: Request, _=Depends(verify_token)):
  8. """获取完整知识树"""
  9. config = request.app.state.config
  10. conn = get_connection(config.db_path)
  11. try:
  12. points = get_knowledge_tree(conn)
  13. # 构建树结构
  14. tree = _build_tree(points)
  15. return {"tree": tree, "total_leaves": len(points)}
  16. finally:
  17. conn.close()
  18. @router.get("/knowledge/search")
  19. def search_knowledge_api(
  20. request: Request,
  21. q: str = Query(..., min_length=1),
  22. limit: int = Query(30, le=100),
  23. _=Depends(verify_token),
  24. ):
  25. """搜索知识点"""
  26. config = request.app.state.config
  27. conn = get_connection(config.db_path)
  28. try:
  29. results = search_knowledge(conn, q, limit)
  30. return {"results": results}
  31. finally:
  32. conn.close()
  33. def _build_tree(points: list[dict]) -> list[dict]:
  34. """将扁平知识点列表构建为树结构"""
  35. tree = {}
  36. for p in points:
  37. code = p["code"]
  38. path = p.get("path", "")
  39. # path 格式: "章 > 节 > 小节 > 项 > 叶子"
  40. path_parts = path.split(" > ")
  41. parts = code.split(".")
  42. chapter_key = parts[0]
  43. section_key = f"{parts[0]}.{parts[1]}"
  44. sub_key = f"{parts[0]}.{parts[1]}.{parts[2]}"
  45. item_key = f"{parts[0]}.{parts[1]}.{parts[2]}.{parts[3]}"
  46. chapter_name = path_parts[0] if len(path_parts) > 0 else chapter_key
  47. section_name = path_parts[1] if len(path_parts) > 1 else section_key
  48. sub_name = path_parts[2] if len(path_parts) > 2 else sub_key
  49. item_name = path_parts[3] if len(path_parts) > 3 else item_key
  50. # 章
  51. if chapter_key not in tree:
  52. tree[chapter_key] = {"code": chapter_key, "name": chapter_name, "children": {}}
  53. # 节
  54. chapter = tree[chapter_key]["children"]
  55. if section_key not in chapter:
  56. chapter[section_key] = {"code": section_key, "name": section_name, "children": {}}
  57. # 小节
  58. section = chapter[section_key]["children"]
  59. if sub_key not in section:
  60. section[sub_key] = {"code": sub_key, "name": sub_name, "children": {}}
  61. # 项
  62. sub = section[sub_key]["children"]
  63. if item_key not in sub:
  64. sub[item_key] = {"code": item_key, "name": item_name, "children": []}
  65. # 叶子
  66. sub[item_key]["children"].append({
  67. "code": p["code"],
  68. "name": p["leaf_name"],
  69. "full_path": path,
  70. })
  71. # 转为有序列表
  72. def convert(d: dict) -> list:
  73. result = []
  74. for k in sorted(d.keys()):
  75. v = d[k]
  76. node = {"code": v["code"], "name": v["name"]}
  77. if "children" in v:
  78. if isinstance(v["children"], dict):
  79. node["children"] = convert(v["children"])
  80. else:
  81. node["children"] = v["children"]
  82. result.append(node)
  83. return result
  84. return convert(tree)