首次提交by MimoCode
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user, require_role
|
||||
from app.models.user import User
|
||||
from app.config import settings
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/recognize-medicine")
|
||||
async def recognize_medicine(
|
||||
file: UploadFile = File(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
from app.ai.manager import ai_manager
|
||||
|
||||
if not file.content_type.startswith("image/"):
|
||||
raise HTTPException(status_code=400, detail="请上传图片文件")
|
||||
|
||||
image_bytes = await file.read()
|
||||
if len(image_bytes) > settings.MAX_UPLOAD_SIZE:
|
||||
raise HTTPException(status_code=413, detail="文件过大")
|
||||
|
||||
vision_provider = ai_manager.get_vision_provider(settings.AI_PROVIDER)
|
||||
if not vision_provider:
|
||||
raise HTTPException(status_code=500, detail="AI 服务未配置")
|
||||
|
||||
try:
|
||||
result = await vision_provider.recognize_medicine(image_bytes)
|
||||
return result.model_dump()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"识别失败: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/recognize-dates")
|
||||
async def recognize_dates(
|
||||
file: UploadFile = File(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
from app.ai.manager import ai_manager
|
||||
|
||||
if not file.content_type.startswith("image/"):
|
||||
raise HTTPException(status_code=400, detail="请上传图片文件")
|
||||
|
||||
image_bytes = await file.read()
|
||||
if len(image_bytes) > settings.MAX_UPLOAD_SIZE:
|
||||
raise HTTPException(status_code=413, detail="文件过大")
|
||||
|
||||
vision_provider = ai_manager.get_vision_provider(settings.AI_PROVIDER)
|
||||
if not vision_provider:
|
||||
raise HTTPException(status_code=500, detail="AI 服务未配置")
|
||||
|
||||
try:
|
||||
result = await vision_provider.recognize_dates(image_bytes)
|
||||
return result.model_dump()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"识别失败: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/recognize-leaflet")
|
||||
async def recognize_leaflet(
|
||||
file: UploadFile = File(...),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
from app.ai.manager import ai_manager
|
||||
|
||||
if not file.content_type.startswith("image/"):
|
||||
raise HTTPException(status_code=400, detail="请上传图片文件")
|
||||
|
||||
image_bytes = await file.read()
|
||||
if len(image_bytes) > settings.MAX_UPLOAD_SIZE:
|
||||
raise HTTPException(status_code=413, detail="文件过大")
|
||||
|
||||
text_provider = ai_manager.get_text_provider(settings.AI_PROVIDER)
|
||||
if not text_provider:
|
||||
raise HTTPException(status_code=500, detail="AI 服务未配置")
|
||||
|
||||
try:
|
||||
import base64
|
||||
base64_image = base64.b64encode(image_bytes).decode('utf-8')
|
||||
|
||||
from openai import AsyncOpenAI
|
||||
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
|
||||
|
||||
response = await client.chat.completions.create(
|
||||
model=settings.OPENAI_MODEL,
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "请识别这张说明书图片中的文字内容,返回纯文本。"
|
||||
},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": f"data:image/jpeg;base64,{base64_image}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
ocr_text = response.choices[0].message.content
|
||||
result = await text_provider.summarize_leaflet(ocr_text)
|
||||
return result.model_dump()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"识别失败: {str(e)}")
|
||||
@@ -0,0 +1,42 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user
|
||||
from app.services.auth import AuthService
|
||||
from app.schemas.user import UserLogin, Token, UserResponse
|
||||
from app.schemas.auth import PasswordChangeRequest
|
||||
from app.services.user import UserService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/login", response_model=Token)
|
||||
async def login(data: UserLogin, db: AsyncSession = Depends(get_db)):
|
||||
service = AuthService(db)
|
||||
result = await service.login(data.username, data.password)
|
||||
if not result:
|
||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||
return Token(
|
||||
access_token=result["access_token"],
|
||||
token_type=result["token_type"],
|
||||
user=UserResponse.model_validate(result["user"])
|
||||
)
|
||||
|
||||
|
||||
@router.get("/me", response_model=UserResponse)
|
||||
async def get_current_user_info(current_user=Depends(get_current_user)):
|
||||
return UserResponse.model_validate(current_user)
|
||||
|
||||
|
||||
@router.put("/password")
|
||||
async def change_password(
|
||||
data: PasswordChangeRequest,
|
||||
current_user=Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
service = UserService(db)
|
||||
success = await service.change_password(current_user.id, data.old_password, data.new_password)
|
||||
if not success:
|
||||
raise HTTPException(status_code=400, detail="原密码错误")
|
||||
return {"message": "密码修改成功"}
|
||||
@@ -0,0 +1,104 @@
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user, require_role
|
||||
from app.models.user import User
|
||||
from app.schemas.batch import BatchCreate, BatchUpdate, BatchResponse, BatchDispense, BatchAddStock
|
||||
from app.services.batch import BatchService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/medicine/{medicine_id}", response_model=List[BatchResponse])
|
||||
async def list_batches_by_medicine(
|
||||
medicine_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = BatchService(db)
|
||||
batches = await service.get_batches_by_medicine(medicine_id)
|
||||
return [BatchResponse.model_validate(b) for b in batches]
|
||||
|
||||
|
||||
@router.get("/{batch_id}", response_model=BatchResponse)
|
||||
async def get_batch(
|
||||
batch_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = BatchService(db)
|
||||
batch = await service.get_batch(batch_id)
|
||||
if not batch:
|
||||
raise HTTPException(status_code=404, detail="批次不存在")
|
||||
return BatchResponse.model_validate(batch)
|
||||
|
||||
|
||||
@router.post("/medicine/{medicine_id}", response_model=BatchResponse)
|
||||
async def create_batch(
|
||||
medicine_id: int,
|
||||
data: BatchCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
service = BatchService(db)
|
||||
batch = await service.create_batch(medicine_id, data)
|
||||
return BatchResponse.model_validate(batch)
|
||||
|
||||
|
||||
@router.put("/{batch_id}", response_model=BatchResponse)
|
||||
async def update_batch(
|
||||
batch_id: int,
|
||||
data: BatchUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
service = BatchService(db)
|
||||
batch = await service.update_batch(batch_id, data)
|
||||
if not batch:
|
||||
raise HTTPException(status_code=404, detail="批次不存在")
|
||||
return BatchResponse.model_validate(batch)
|
||||
|
||||
|
||||
@router.delete("/{batch_id}")
|
||||
async def delete_batch(
|
||||
batch_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = BatchService(db)
|
||||
success = await service.delete_batch(batch_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="批次不存在")
|
||||
return {"message": "删除成功"}
|
||||
|
||||
|
||||
@router.post("/{batch_id}/dispense", response_model=BatchResponse)
|
||||
async def dispense_batch(
|
||||
batch_id: int,
|
||||
data: BatchDispense,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
service = BatchService(db)
|
||||
try:
|
||||
batch = await service.dispense(batch_id, data.quantity, current_user.id)
|
||||
return BatchResponse.model_validate(batch)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
|
||||
@router.post("/{batch_id}/add-stock", response_model=BatchResponse)
|
||||
async def add_stock_batch(
|
||||
batch_id: int,
|
||||
data: BatchAddStock,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
service = BatchService(db)
|
||||
try:
|
||||
batch = await service.add_stock(batch_id, data.quantity, current_user.id)
|
||||
return BatchResponse.model_validate(batch)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
@@ -0,0 +1,83 @@
|
||||
from typing import Optional, List
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user, require_role
|
||||
from app.models.user import User
|
||||
from app.schemas.category import CategoryCreate, CategoryUpdate, CategoryResponse
|
||||
from app.services.category import CategoryService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def list_categories(
|
||||
level: Optional[int] = Query(None),
|
||||
parent_id: Optional[int] = Query(None),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = CategoryService(db)
|
||||
categories = await service.get_categories(level=level, parent_id=parent_id)
|
||||
return [CategoryResponse.model_validate(c) for c in categories]
|
||||
|
||||
|
||||
@router.get("/tree")
|
||||
async def get_category_tree(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = CategoryService(db)
|
||||
return await service.get_category_tree()
|
||||
|
||||
|
||||
@router.get("/{category_id}", response_model=CategoryResponse)
|
||||
async def get_category(
|
||||
category_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = CategoryService(db)
|
||||
category = await service.get_category(category_id)
|
||||
if not category:
|
||||
raise HTTPException(status_code=404, detail="分类不存在")
|
||||
return CategoryResponse.model_validate(category)
|
||||
|
||||
|
||||
@router.post("/", response_model=CategoryResponse)
|
||||
async def create_category(
|
||||
data: CategoryCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = CategoryService(db)
|
||||
category = await service.create_category(data.model_dump())
|
||||
return CategoryResponse.model_validate(category)
|
||||
|
||||
|
||||
@router.put("/{category_id}", response_model=CategoryResponse)
|
||||
async def update_category(
|
||||
category_id: int,
|
||||
data: CategoryUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = CategoryService(db)
|
||||
category = await service.update_category(category_id, data.model_dump(exclude_unset=True))
|
||||
if not category:
|
||||
raise HTTPException(status_code=404, detail="分类不存在")
|
||||
return CategoryResponse.model_validate(category)
|
||||
|
||||
|
||||
@router.delete("/{category_id}")
|
||||
async def delete_category(
|
||||
category_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = CategoryService(db)
|
||||
success = await service.delete_category(category_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="分类不存在")
|
||||
return {"message": "删除成功"}
|
||||
@@ -0,0 +1,86 @@
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user, require_role
|
||||
from app.models.user import User
|
||||
from app.schemas.medicine import MedicineCreate, MedicineUpdate, MedicineResponse, MedicineWithStock
|
||||
from app.services.medicine import MedicineService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def list_medicines(
|
||||
category_id: Optional[int] = Query(None),
|
||||
search: Optional[str] = Query(None),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = MedicineService(db)
|
||||
medicines, total = await service.get_medicines(
|
||||
category_id=category_id,
|
||||
search=search,
|
||||
page=page,
|
||||
page_size=page_size
|
||||
)
|
||||
return {
|
||||
"data": [MedicineWithStock.model_validate(m) for m in medicines],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": page_size
|
||||
}
|
||||
|
||||
|
||||
@router.get("/{medicine_id}", response_model=MedicineResponse)
|
||||
async def get_medicine(
|
||||
medicine_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = MedicineService(db)
|
||||
medicine = await service.get_medicine(medicine_id)
|
||||
if not medicine:
|
||||
raise HTTPException(status_code=404, detail="药品不存在")
|
||||
return MedicineResponse.model_validate(medicine)
|
||||
|
||||
|
||||
@router.post("/", response_model=MedicineResponse)
|
||||
async def create_medicine(
|
||||
data: MedicineCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
service = MedicineService(db)
|
||||
medicine = await service.create_medicine(data, current_user.id)
|
||||
return MedicineResponse.model_validate(medicine)
|
||||
|
||||
|
||||
@router.put("/{medicine_id}", response_model=MedicineResponse)
|
||||
async def update_medicine(
|
||||
medicine_id: int,
|
||||
data: MedicineUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin", "user"]))
|
||||
):
|
||||
service = MedicineService(db)
|
||||
medicine = await service.update_medicine(medicine_id, data)
|
||||
if not medicine:
|
||||
raise HTTPException(status_code=404, detail="药品不存在")
|
||||
return MedicineResponse.model_validate(medicine)
|
||||
|
||||
|
||||
@router.delete("/{medicine_id}")
|
||||
async def delete_medicine(
|
||||
medicine_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = MedicineService(db)
|
||||
success = await service.delete_medicine(medicine_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="药品不存在")
|
||||
return {"message": "删除成功"}
|
||||
@@ -0,0 +1,77 @@
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user
|
||||
from app.models.user import User
|
||||
from app.services.notification import NotificationService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def list_notifications(
|
||||
is_read: Optional[bool] = Query(None),
|
||||
type: Optional[str] = Query(None),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = NotificationService(db)
|
||||
notifications = await service.get_notifications(
|
||||
user_id=current_user.id,
|
||||
is_read=is_read,
|
||||
type=type,
|
||||
page=page,
|
||||
page_size=page_size
|
||||
)
|
||||
return [
|
||||
{
|
||||
"id": n.id,
|
||||
"type": n.type,
|
||||
"title": n.title,
|
||||
"content": n.content,
|
||||
"is_read": n.is_read,
|
||||
"related_id": n.related_id,
|
||||
"created_at": n.created_at
|
||||
}
|
||||
for n in notifications
|
||||
]
|
||||
|
||||
|
||||
@router.put("/{notification_id}/read")
|
||||
async def mark_notification_read(
|
||||
notification_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = NotificationService(db)
|
||||
success = await service.mark_as_read(notification_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="通知不存在")
|
||||
return {"message": "success"}
|
||||
|
||||
|
||||
@router.put("/read-all")
|
||||
async def mark_all_notifications_read(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = NotificationService(db)
|
||||
count = await service.mark_all_as_read(current_user.id)
|
||||
return {"message": "success", "count": count}
|
||||
|
||||
|
||||
@router.delete("/{notification_id}")
|
||||
async def delete_notification(
|
||||
notification_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = NotificationService(db)
|
||||
success = await service.delete_notification(notification_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="通知不存在")
|
||||
return {"message": "删除成功"}
|
||||
@@ -0,0 +1,66 @@
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import get_current_user
|
||||
from app.models.user import User
|
||||
from app.services.medicine import MedicineService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class NaturalSearchRequest(BaseModel):
|
||||
query: str
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def search_medicines(
|
||||
q: str = Query(...),
|
||||
type: str = Query("name"),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
service = MedicineService(db)
|
||||
medicines = await service.search_medicines(q)
|
||||
return [
|
||||
{
|
||||
"id": m.id,
|
||||
"name": m.name,
|
||||
"generic_name": m.generic_name,
|
||||
"indications": m.indications,
|
||||
"total_quantity": sum(b.quantity for b in m.batches if not b.is_expired)
|
||||
}
|
||||
for m in medicines
|
||||
]
|
||||
|
||||
|
||||
@router.post("/natural")
|
||||
async def natural_language_search(
|
||||
data: NaturalSearchRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
):
|
||||
from app.ai.manager import ai_manager
|
||||
from app.config import settings
|
||||
|
||||
service = MedicineService(db)
|
||||
medicines = await service.search_medicines(data.query)
|
||||
|
||||
if not medicines:
|
||||
return {"results": [], "ai_response": "未找到相关药品"}
|
||||
|
||||
text_provider = ai_manager.get_text_provider(settings.AI_PROVIDER)
|
||||
if not text_provider:
|
||||
return {"results": [], "ai_response": "AI 服务未配置"}
|
||||
|
||||
medicines_data = [
|
||||
{"name": m.name, "indications": m.indications or ""}
|
||||
for m in medicines
|
||||
]
|
||||
|
||||
try:
|
||||
results = await text_provider.natural_language_search(data.query, medicines_data)
|
||||
return {"results": results, "ai_response": "搜索完成"}
|
||||
except Exception as e:
|
||||
return {"results": [], "ai_response": f"搜索失败: {str(e)}"}
|
||||
@@ -0,0 +1,82 @@
|
||||
from typing import List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import require_role
|
||||
from app.models.user import User
|
||||
from app.models.setting import Setting
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class SettingResponse(BaseModel):
|
||||
key: str
|
||||
value: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class SettingUpdate(BaseModel):
|
||||
value: str
|
||||
|
||||
|
||||
class BulkSettingUpdate(BaseModel):
|
||||
settings: List[SettingUpdate]
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def list_settings(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
result = await db.execute(select(Setting))
|
||||
settings = list(result.scalars().all())
|
||||
return [
|
||||
{
|
||||
"key": s.key,
|
||||
"value": s.value,
|
||||
"description": s.description
|
||||
}
|
||||
for s in settings
|
||||
]
|
||||
|
||||
|
||||
@router.get("/{key}", response_model=SettingResponse)
|
||||
async def get_setting(
|
||||
key: str,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
result = await db.execute(select(Setting).where(Setting.key == key))
|
||||
setting = result.scalar_one_or_none()
|
||||
if not setting:
|
||||
raise HTTPException(status_code=404, detail="设置不存在")
|
||||
return SettingResponse(
|
||||
key=setting.key,
|
||||
value=setting.value,
|
||||
description=setting.description
|
||||
)
|
||||
|
||||
|
||||
@router.put("/{key}", response_model=SettingResponse)
|
||||
async def update_setting(
|
||||
key: str,
|
||||
data: SettingUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
result = await db.execute(select(Setting).where(Setting.key == key))
|
||||
setting = result.scalar_one_or_none()
|
||||
if not setting:
|
||||
setting = Setting(key=key, value=data.value)
|
||||
db.add(setting)
|
||||
else:
|
||||
setting.value = data.value
|
||||
await db.commit()
|
||||
return SettingResponse(
|
||||
key=setting.key,
|
||||
value=setting.value,
|
||||
description=setting.description
|
||||
)
|
||||
@@ -0,0 +1,94 @@
|
||||
from typing import List
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.database import get_db
|
||||
from app.core.deps import require_role
|
||||
from app.models.user import User
|
||||
from app.schemas.user import UserCreate, UserUpdate, UserResponse
|
||||
from app.services.user import UserService
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class ResetPasswordRequest(BaseModel):
|
||||
new_password: str
|
||||
|
||||
|
||||
@router.get("/", response_model=List[UserResponse])
|
||||
async def list_users(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = UserService(db)
|
||||
users = await service.get_all_users()
|
||||
return [UserResponse.model_validate(u) for u in users]
|
||||
|
||||
|
||||
@router.get("/{user_id}", response_model=UserResponse)
|
||||
async def get_user(
|
||||
user_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = UserService(db)
|
||||
user = await service.get_user(user_id)
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return UserResponse.model_validate(user)
|
||||
|
||||
|
||||
@router.post("/", response_model=UserResponse)
|
||||
async def create_user(
|
||||
data: UserCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = UserService(db)
|
||||
existing_user = await service.get_user_by_username(data.username)
|
||||
if existing_user:
|
||||
raise HTTPException(status_code=409, detail="用户名已存在")
|
||||
user = await service.create_user(data.model_dump())
|
||||
return UserResponse.model_validate(user)
|
||||
|
||||
|
||||
@router.put("/{user_id}", response_model=UserResponse)
|
||||
async def update_user(
|
||||
user_id: int,
|
||||
data: UserUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = UserService(db)
|
||||
user = await service.update_user(user_id, data.model_dump(exclude_unset=True))
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return UserResponse.model_validate(user)
|
||||
|
||||
|
||||
@router.delete("/{user_id}")
|
||||
async def delete_user(
|
||||
user_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = UserService(db)
|
||||
success = await service.delete_user(user_id)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return {"message": "删除成功"}
|
||||
|
||||
|
||||
@router.post("/{user_id}/reset-password")
|
||||
async def reset_password(
|
||||
user_id: int,
|
||||
data: ResetPasswordRequest,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_role(["admin"]))
|
||||
):
|
||||
service = UserService(db)
|
||||
success = await service.reset_password(user_id, data.new_password)
|
||||
if not success:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
return {"message": "success"}
|
||||
Reference in New Issue
Block a user