| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- """公开 API:附件上传、反馈/建言提交、热线/二维码读取(无需登录)。"""
- from typing import Annotated, Optional
- from fastapi import APIRouter, Depends, File, Form, UploadFile
- from sqlalchemy.orm import Session
- from app.core import storage
- from app.core.database import get_db
- from app.core.response import AppHTTPError, success_response
- from app.core.storage import StorageError
- from app.core.storage import _normalize_folder
- from app.core.upload_validate import validate_upload
- from app.crud import attachment as attachment_crud
- from app.schemas.business import FeedbackCreateBody, SuggestionCreateBody
- from app.services import config_service, feedback_service, suggestion_service
- router = APIRouter(prefix="/public", tags=["public"])
- PUBLIC_UPLOAD_FOLDERS = frozenset({"feedback", "suggestion"})
- @router.post("/attachment/upload")
- async def upload_attachment(
- db: Annotated[Session, Depends(get_db)],
- file: UploadFile = File(...),
- folder: Optional[str] = Form(""),
- ):
- if not file or not file.filename:
- raise AppHTTPError(400, "请选择文件")
- try:
- folder_norm = _normalize_folder(folder or "")
- except StorageError as exc:
- raise AppHTTPError(400, exc.message) from exc
- if folder_norm not in PUBLIC_UPLOAD_FOLDERS:
- raise AppHTTPError(400, "不允许的上传目录")
- content = await file.read()
- validate_upload(file.filename, content)
- try:
- stored = storage.upload_file(content, file.filename, folder_norm)
- except StorageError as exc:
- raise AppHTTPError(400, exc.message) from exc
- row = attachment_crud.create_attachment(
- db,
- file_name=file.filename,
- object_key=stored["objectKey"],
- url=stored["url"],
- size=len(content),
- )
- return success_response(
- {
- "id": row.id,
- "url": row.url,
- "fileName": row.file_name,
- "size": row.size,
- }
- )
- @router.get("/hotline")
- def get_hotline(db: Annotated[Session, Depends(get_db)]):
- return success_response(config_service.get_hotline_payload(db))
- @router.get("/qrcode")
- def get_qrcode(db: Annotated[Session, Depends(get_db)]):
- return success_response(config_service.get_qrcode_payload(db))
- @router.post("/feedback")
- def submit_feedback(
- body: FeedbackCreateBody,
- db: Annotated[Session, Depends(get_db)],
- ):
- data = feedback_service.submit_feedback(
- db,
- fb_type=body.fb_type,
- content=body.content,
- target_name=body.target_name,
- target_dept=body.target_dept,
- target_post=body.target_post,
- reporter_name=body.reporter_name,
- reporter_unit=body.reporter_unit,
- reporter_post=body.reporter_post,
- reporter_phone=body.reporter_phone,
- attachment_urls=body.attachment_urls,
- )
- return success_response(data)
- @router.post("/suggestion")
- def submit_suggestion(
- body: SuggestionCreateBody,
- db: Annotated[Session, Depends(get_db)],
- ):
- data = suggestion_service.submit_suggestion(
- db,
- content=body.content,
- contact_name=body.contact_name,
- contact_unit=body.contact_unit,
- contact_post=body.contact_post,
- contact_phone=body.contact_phone,
- attachment_urls=body.attachment_urls,
- )
- return success_response(data)
|