BookSystem/backend/auth/apps/settings/urls.py
jayhgq 924885e038 feat: 添加页脚和ICP备案信息到系统设置和页面
1. 新增页脚信息和ICP备案信息的系统配置项
2. 开放公开接口获取新增的系统设置项
3. 在管理端布局添加页脚和ICP备案展示
2026-06-10 14:49:01 +08:00

205 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import APIRouter, Depends, HTTPException, File, UploadFile
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_
from fastcrud import FastCRUD
from pathlib import Path
import os
import shutil
from datetime import datetime
from database import get_db
from models import SystemSetting, User
from schemas import (
SystemSettingCreate,
SystemSettingUpdate,
SystemSettingResponse,
)
from middleware import get_current_user
from utils.like_filter import ilike_contains
router = APIRouter(prefix="/settings", tags=["settings"])
# 创建FastCRUD实例
setting_crud = FastCRUD(SystemSetting, SystemSettingResponse)
# 图片存储目录
UPLOAD_DIR = Path(__file__).parent.parent.parent / "uploads"
UPLOAD_DIR.mkdir(exist_ok=True)
@router.post("/", response_model=SystemSettingResponse)
async def create_setting(
setting_data: SystemSettingCreate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""创建设置项"""
# 检查设置键名是否已存在
result = await db.execute(select(SystemSetting).filter(SystemSetting.key == setting_data.key))
existing_setting = result.scalar_one_or_none()
if existing_setting:
raise HTTPException(status_code=400, detail="设置键名已存在")
# 创建设置实例
db_setting = SystemSetting(
key=setting_data.key,
value=setting_data.value,
type=setting_data.type or "string",
options=setting_data.options,
description=setting_data.description,
)
db.add(db_setting)
await db.commit()
await db.refresh(db_setting)
return db_setting
@router.get("/", response_model=list[SystemSettingResponse])
async def get_settings(
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""获取所有设置项"""
result = await db.execute(select(SystemSetting))
settings = result.scalars().all()
return [SystemSettingResponse.model_validate(s) for s in settings]
@router.get("/public", response_model=SystemSettingResponse)
async def get_public_setting(
setting_id: int = None,
key: str = None,
db: AsyncSession = Depends(get_db),
):
"""公开接口获取系统设置允许获取id为1/2或key为"系统标题"/"IPC内容"的内容)"""
ALLOWED_IDS = {1, 2, 3}
ALLOWED_KEYS = {"系统标题", "页脚信息", "IPC信息"}
if setting_id is not None:
if setting_id not in ALLOWED_IDS:
raise HTTPException(status_code=403, detail="无权访问该设置项")
result = await db.execute(select(SystemSetting).filter(SystemSetting.id == setting_id))
elif key is not None:
if key not in ALLOWED_KEYS:
raise HTTPException(status_code=403, detail="无权访问该设置项")
result = await db.execute(select(SystemSetting).filter(SystemSetting.key == key))
else:
raise HTTPException(status_code=400, detail="必须提供setting_id或key参数")
setting = result.scalar_one_or_none()
if not setting:
raise HTTPException(status_code=404, detail="设置项不存在")
return setting
@router.get("/{setting_id}", response_model=SystemSettingResponse)
async def get_setting(
setting_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""获取单个设置项"""
setting = await setting_crud.get(db, id=setting_id)
if not setting:
raise HTTPException(status_code=404, detail="设置项不存在")
return setting
@router.get("/key/{key}", response_model=SystemSettingResponse)
async def get_setting_by_key(
key: str,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""根据键名获取设置项"""
result = await db.execute(select(SystemSetting).filter(SystemSetting.key == key))
setting = result.scalar_one_or_none()
if not setting:
raise HTTPException(status_code=404, detail="设置项不存在")
return setting
@router.put("/{setting_id}", response_model=SystemSettingResponse)
async def update_setting(
setting_id: int,
setting_data: SystemSettingUpdate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""更新设置项"""
# 检查设置键名是否被其他设置使用
if setting_data.key:
result = await db.execute(
select(SystemSetting).filter(SystemSetting.key == setting_data.key, SystemSetting.id != setting_id)
)
existing_setting = result.scalar_one_or_none()
if existing_setting:
raise HTTPException(status_code=400, detail="设置键名已存在")
# 准备更新数据
update_data = setting_data.model_dump(exclude_unset=True)
# 使用FastCRUD更新设置
updated_setting = await setting_crud.update(
db, update_data, id=setting_id, schema_to_select=SystemSettingResponse, return_as_model=True
)
if not updated_setting:
raise HTTPException(status_code=404, detail="设置项不存在")
return updated_setting
@router.delete("/{setting_id}")
async def delete_setting(
setting_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
"""删除设置项"""
# 检查设置是否存在
result = await db.execute(select(SystemSetting).filter(SystemSetting.id == setting_id))
existing_setting = result.scalar_one_or_none()
if not existing_setting:
raise HTTPException(status_code=404, detail="设置项不存在")
# 使用FastCRUD删除设置
deleted = await setting_crud.delete(db, id=setting_id)
return {"message": "设置项删除成功"}
@router.post("/upload")
async def upload_image(
file: UploadFile = File(...),
current_user: User = Depends(get_current_user),
):
"""上传图片"""
# 检查文件类型
if not file.filename or not file.filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')):
raise HTTPException(status_code=400, detail="只支持图片格式png, jpg, jpeg, gif, webp")
# 检查文件大小2MB
file_size = 0
chunk = await file.read(1024)
while chunk:
file_size += len(chunk)
if file_size > 2 * 1024 * 1024:
raise HTTPException(status_code=400, detail="文件大小不能超过2MB")
chunk = await file.read(1024)
# 重置文件指针
await file.seek(0)
# 生成文件名
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
ext = file.filename.split('.')[-1]
filename = f"setting_{timestamp}.{ext}"
file_path = UPLOAD_DIR / filename
# 保存文件
with open(file_path, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
# 返回文件路径
return {"url": f"/uploads/{filename}"}