admin.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. """管理端 API:工作台、台账办理、配置、附件上传。"""
  2. from typing import Annotated, Optional
  3. from fastapi import APIRouter, Depends, File, Form, Query, UploadFile
  4. from sqlalchemy.orm import Session
  5. from app.core import storage
  6. from app.core.database import get_db
  7. from app.core.deps import get_current_user, require_menu
  8. from app.core.response import AppHTTPError, success_response
  9. from app.core.storage import StorageError
  10. from app.crud import attachment as attachment_crud
  11. from app.models.system import SysUser
  12. from app.schemas.business import HotlineUpdateBody, QrcodeUpdateBody, StatusUpdateBody
  13. from app.services import admin_ledger_service, config_service, dashboard_service
  14. router = APIRouter(prefix="/web/admin", tags=["admin"])
  15. @router.get("/dashboard")
  16. def dashboard(
  17. db: Annotated[Session, Depends(get_db)],
  18. _user: Annotated[SysUser, Depends(get_current_user)],
  19. ):
  20. return success_response(dashboard_service.get_dashboard(db))
  21. @router.get("/feedbacks")
  22. def list_feedbacks(
  23. db: Annotated[Session, Depends(get_db)],
  24. _user: Annotated[SysUser, Depends(get_current_user)],
  25. status: Optional[str] = Query(None),
  26. fbType: Optional[str] = Query(None),
  27. keyword: Optional[str] = Query(None),
  28. page: int = Query(1, ge=1),
  29. pageSize: int = Query(10, ge=1, le=100),
  30. ):
  31. return success_response(
  32. admin_ledger_service.list_feedbacks_page(
  33. db,
  34. status=status,
  35. fb_type=fbType,
  36. keyword=keyword,
  37. page=page,
  38. page_size=pageSize,
  39. )
  40. )
  41. @router.get("/feedbacks/{feedback_id}")
  42. def get_feedback(
  43. feedback_id: str,
  44. db: Annotated[Session, Depends(get_db)],
  45. _user: Annotated[SysUser, Depends(get_current_user)],
  46. ):
  47. return success_response(
  48. admin_ledger_service.get_feedback_detail(db, feedback_id)
  49. )
  50. @router.put("/feedbacks/{feedback_id}/status")
  51. def update_feedback_status(
  52. feedback_id: str,
  53. body: StatusUpdateBody,
  54. db: Annotated[Session, Depends(get_db)],
  55. user: Annotated[SysUser, Depends(require_menu("feedback:handle"))],
  56. ):
  57. return success_response(
  58. admin_ledger_service.update_feedback_status(
  59. db,
  60. user,
  61. feedback_id,
  62. status=body.status,
  63. handle_remark=body.handle_remark,
  64. )
  65. )
  66. @router.get("/suggestions")
  67. def list_suggestions(
  68. db: Annotated[Session, Depends(get_db)],
  69. _user: Annotated[SysUser, Depends(get_current_user)],
  70. status: Optional[str] = Query(None),
  71. keyword: Optional[str] = Query(None),
  72. page: int = Query(1, ge=1),
  73. pageSize: int = Query(10, ge=1, le=100),
  74. ):
  75. return success_response(
  76. admin_ledger_service.list_suggestions_page(
  77. db,
  78. status=status,
  79. keyword=keyword,
  80. page=page,
  81. page_size=pageSize,
  82. )
  83. )
  84. @router.get("/suggestions/{suggestion_id}")
  85. def get_suggestion(
  86. suggestion_id: str,
  87. db: Annotated[Session, Depends(get_db)],
  88. _user: Annotated[SysUser, Depends(get_current_user)],
  89. ):
  90. return success_response(
  91. admin_ledger_service.get_suggestion_detail(db, suggestion_id)
  92. )
  93. @router.put("/suggestions/{suggestion_id}/status")
  94. def update_suggestion_status(
  95. suggestion_id: str,
  96. body: StatusUpdateBody,
  97. db: Annotated[Session, Depends(get_db)],
  98. user: Annotated[SysUser, Depends(require_menu("suggestion:handle"))],
  99. ):
  100. return success_response(
  101. admin_ledger_service.update_suggestion_status(
  102. db,
  103. user,
  104. suggestion_id,
  105. status=body.status,
  106. handle_remark=body.handle_remark,
  107. )
  108. )
  109. @router.get("/hotline")
  110. def get_hotline(
  111. db: Annotated[Session, Depends(get_db)],
  112. _user: Annotated[SysUser, Depends(get_current_user)],
  113. ):
  114. return success_response(config_service.get_hotline_payload(db))
  115. @router.put("/hotline")
  116. def put_hotline(
  117. body: HotlineUpdateBody,
  118. db: Annotated[Session, Depends(get_db)],
  119. user: Annotated[SysUser, Depends(require_menu("hotline:write"))],
  120. ):
  121. return success_response(
  122. config_service.update_hotline(
  123. db,
  124. user,
  125. phone=body.phone,
  126. email=body.email,
  127. address=body.address,
  128. work_time=body.work_time,
  129. )
  130. )
  131. @router.get("/qrcode")
  132. def get_qrcode(
  133. db: Annotated[Session, Depends(get_db)],
  134. _user: Annotated[SysUser, Depends(get_current_user)],
  135. ):
  136. return success_response(config_service.get_qrcode_payload(db))
  137. @router.put("/qrcode")
  138. def put_qrcode(
  139. body: QrcodeUpdateBody,
  140. db: Annotated[Session, Depends(get_db)],
  141. user: Annotated[SysUser, Depends(require_menu("qrcode:write"))],
  142. ):
  143. return success_response(
  144. config_service.update_qrcode(
  145. db,
  146. user,
  147. land_url=body.land_url,
  148. title=body.title,
  149. image_url=body.image_url,
  150. )
  151. )
  152. @router.post("/attachment/upload")
  153. async def admin_upload(
  154. db: Annotated[Session, Depends(get_db)],
  155. _user: Annotated[SysUser, Depends(get_current_user)],
  156. file: UploadFile = File(...),
  157. folder: Optional[str] = Form(""),
  158. ):
  159. if not file or not file.filename:
  160. raise AppHTTPError(400, "请选择文件")
  161. content = await file.read()
  162. try:
  163. stored = storage.upload_file(content, file.filename, folder or "")
  164. except StorageError as exc:
  165. raise AppHTTPError(400, exc.message) from exc
  166. row = attachment_crud.create_attachment(
  167. db,
  168. file_name=file.filename,
  169. object_key=stored["objectKey"],
  170. url=stored["url"],
  171. size=len(content),
  172. )
  173. return success_response(
  174. {
  175. "id": row.id,
  176. "url": row.url,
  177. "fileName": row.file_name,
  178. "size": row.size,
  179. }
  180. )