drug.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from typing import Optional
  2. from fastapi import APIRouter, Depends, HTTPException, Query
  3. from sqlalchemy import text
  4. from sqlalchemy.ext.asyncio import AsyncSession
  5. from app.core.security import get_current_user
  6. from app.models.drug import get_db
  7. router = APIRouter(prefix="/drug", tags=["药品"])
  8. @router.get("/search")
  9. async def search_drug(
  10. keyword: Optional[str] = Query(None),
  11. category: Optional[str] = Query(None),
  12. page: int = Query(1, ge=1),
  13. page_size: int = Query(20, ge=1, le=100),
  14. user: dict = Depends(get_current_user),
  15. ):
  16. db = get_db()
  17. offset = (page - 1) * page_size
  18. conditions = ["is_active = TRUE"]
  19. params = {}
  20. if keyword:
  21. conditions.append("(name ILIKE :kw OR pinyin ILIKE :kw OR name_en ILIKE :kw)")
  22. params["kw"] = f"%{keyword}%"
  23. if category:
  24. conditions.append("category = :cat")
  25. params["cat"] = category
  26. where = "WHERE " + " AND ".join(conditions)
  27. count_query = f"SELECT COUNT(*) FROM drugs {where}"
  28. data_query = f"""
  29. SELECT drug_id, name, name_en, pinyin, category, subcategory,
  30. source_version, source_volume, source_page, is_active
  31. FROM drugs {where}
  32. ORDER BY name
  33. LIMIT :limit OFFSET :offset
  34. """
  35. params["limit"] = page_size
  36. params["offset"] = offset
  37. async with db() as session:
  38. total = (await session.execute(text(count_query), params)).scalar()
  39. rows = (await session.execute(text(data_query), params)).fetchall()
  40. items = []
  41. for row in rows:
  42. items.append({
  43. "drug_id": row.drug_id,
  44. "name": row.name,
  45. "name_en": row.name_en or "",
  46. "pinyin": row.pinyin or "",
  47. "category": row.category or "",
  48. "subcategory": row.subcategory or "",
  49. "source_version": row.source_version or "",
  50. "source_volume": row.source_volume or "",
  51. "source_page": row.source_page or "",
  52. "is_active": row.is_active,
  53. })
  54. total_pages = max(1, (total + page_size - 1) // page_size)
  55. return {
  56. "items": items,
  57. "total": total,
  58. "page": page,
  59. "page_size": page_size,
  60. "total_pages": total_pages,
  61. }
  62. @router.get("/{drug_id}")
  63. async def get_drug_detail(
  64. drug_id: str,
  65. user: dict = Depends(get_current_user),
  66. ):
  67. db = get_db()
  68. async with db() as session:
  69. row = (await session.execute(
  70. text("SELECT * FROM drugs WHERE drug_id = :drug_id"),
  71. {"drug_id": drug_id}
  72. )).fetchone()
  73. if not row:
  74. raise HTTPException(status_code=404, detail="Drug not found")
  75. return {
  76. "data": {
  77. "drug_id": row.drug_id,
  78. "name": row.name,
  79. "name_en": row.name_en or "",
  80. "pinyin": row.pinyin or "",
  81. "category": row.category or "",
  82. "subcategory": row.subcategory or "",
  83. "sections": row.sections or {},
  84. "source_version": row.source_version or "",
  85. "source_volume": row.source_volume or "",
  86. "source_page": row.source_page or "",
  87. "is_active": row.is_active,
  88. }
  89. }
  90. @router.get("/category/tree")
  91. async def get_category_tree(user: dict = Depends(get_current_user)):
  92. db = get_db()
  93. async with db() as session:
  94. rows = (await session.execute(
  95. text("SELECT DISTINCT category, subcategory FROM drugs WHERE category IS NOT NULL ORDER BY category, subcategory")
  96. )).fetchall()
  97. tree = {}
  98. for row in rows:
  99. cat = row.category
  100. sub = row.subcategory or ""
  101. if cat not in tree:
  102. tree[cat] = []
  103. if sub and sub not in tree[cat]:
  104. tree[cat].append(sub)
  105. return {"tree": [{"name": k, "children": v} for k, v in tree.items()]}