支持管理员读写设置

This commit is contained in:
2026-01-08 14:54:30 +08:00
parent baf59b9903
commit 91208352f8
3 changed files with 69 additions and 37 deletions

View File

@@ -73,7 +73,7 @@ from .report import Report, ReportReason
from .setting import ( from .setting import (
Setting, SettingsType, SiteConfigResponse, Setting, SettingsType, SiteConfigResponse,
# 管理员DTO # 管理员DTO
SettingItem, SettingsUpdateRequest, SettingsGetResponse, SettingItem, SettingsListResponse, SettingsUpdateRequest, SettingsUpdateResponse,
) )
from .share import Share from .share import Share
from .source_link import SourceLink from .source_link import SourceLink

View File

@@ -48,7 +48,10 @@ class SiteConfigResponse(SQLModelBase):
# ==================== 管理员设置 DTO ==================== # ==================== 管理员设置 DTO ====================
class SettingItem(SQLModelBase): class SettingItem(SQLModelBase):
"""设置项 DTO""" """单个设置项 DTO"""
type: str
"""设置类型"""
name: str name: str
"""设置项名称""" """设置项名称"""
@@ -57,18 +60,31 @@ class SettingItem(SQLModelBase):
"""设置值""" """设置值"""
class SettingsListResponse(SQLModelBase):
"""获取设置列表响应 DTO"""
settings: list[SettingItem]
"""设置项列表"""
total: int
"""总数"""
class SettingsUpdateRequest(SQLModelBase): class SettingsUpdateRequest(SQLModelBase):
"""更新设置请求 DTO""" """更新设置请求 DTO"""
settings: dict[str, dict[str, str | None]] settings: list[SettingItem]
"""按类型分组的设置项,格式: {"basic": {"siteName": "xxx", ...}, ...}""" """要更新的设置项列表"""
class SettingsGetResponse(SQLModelBase): class SettingsUpdateResponse(SQLModelBase):
"""获取设置响应 DTO""" """更新设置响应 DTO"""
settings: dict[str, dict[str, str | None]] = {} updated: int
"""按类型分组的设置项""" """更新的设置项数量"""
created: int
"""新建的设置项数量"""
# ==================== 数据库模型 ==================== # ==================== 数据库模型 ====================

View File

@@ -24,7 +24,9 @@ from models.group import (
from models.user import ( from models.user import (
UserPublic, UserAdminUpdateRequest, UserCalibrateResponse, UserPublic, UserAdminUpdateRequest, UserCalibrateResponse,
) )
from models.setting import SettingsUpdateRequest, SettingsGetResponse from models.setting import (
SettingItem, SettingsListResponse, SettingsUpdateRequest, SettingsUpdateResponse,
)
from models.object import AdminFileResponse, AdminFileListResponse, FileBanRequest from models.object import AdminFileResponse, AdminFileListResponse, FileBanRequest
from models.policy import GroupPolicyLink from models.policy import GroupPolicyLink
from service.storage import DirectoryCreationError, LocalStorageService from service.storage import DirectoryCreationError, LocalStorageService
@@ -288,34 +290,34 @@ def router_admin_get_news() -> ResponseBase:
async def router_admin_update_settings( async def router_admin_update_settings(
session: SessionDep, session: SessionDep,
request: SettingsUpdateRequest, request: SettingsUpdateRequest,
) -> ResponseBase: ) -> SettingsUpdateResponse:
""" """
批量更新站点设置。 批量更新站点设置。
:param session: 数据库会话 :param session: 数据库会话
:param request: 更新请求,按类型分组的设置项 :param request: 更新请求,设置项列表
:return: 更新结果 :return: 更新结果
""" """
updated_count = 0 updated_count = 0
created_count = 0
for setting_type, items in request.settings.items(): for item in request.settings:
for name, value in items.items():
existing = await Setting.get( existing = await Setting.get(
session, session,
and_(Setting.type == setting_type, Setting.name == name) and_(Setting.type == item.type, Setting.name == item.name)
) )
if existing: if existing:
existing.value = value existing.value = item.value
await existing.save(session) await existing.save(session)
else:
new_setting = Setting(type=setting_type, name=name, value=value)
await new_setting.save(session)
updated_count += 1 updated_count += 1
else:
new_setting = Setting(type=item.type, name=item.name, value=item.value)
await new_setting.save(session)
created_count += 1
l.info(f"管理员更新了 {updated_count} 个设置项") l.info(f"管理员更新了 {updated_count} 个设置项,新建了 {created_count} 个设置项")
return ResponseBase(data={"updated": updated_count}) return SettingsUpdateResponse(updated=updated_count, created=created_count)
@admin_router.get( @admin_router.get(
@@ -324,23 +326,37 @@ async def router_admin_update_settings(
description='Get settings', description='Get settings',
dependencies=[Depends(admin_required)], dependencies=[Depends(admin_required)],
) )
async def router_admin_get_settings(session: SessionDep) -> ResponseBase: async def router_admin_get_settings(
session: SessionDep,
type: str | None = None,
name: str | None = None,
) -> SettingsListResponse:
""" """
获取所有站点设置,按类型分组返回 获取站点设置,支持按类型和名称筛选
:param session: 数据库会话 :param session: 数据库会话
:return: 按类型分组的设置项 :param type: 设置类型(可选筛选条件)
:param name: 设置名称(可选筛选条件)
:return: 设置项列表
""" """
settings = await Setting.get(session, None, fetch_mode="all") # 构建查询条件
conditions = []
if type:
conditions.append(Setting.type == type)
if name:
conditions.append(Setting.name == name)
# 按 type 分组 condition = and_(*conditions) if conditions else None
grouped: dict[str, dict[str, str | None]] = {}
for setting in settings:
if setting.type not in grouped:
grouped[setting.type] = {}
grouped[setting.type][setting.name] = setting.value
return ResponseBase(data=grouped) settings = await Setting.get(session, condition, fetch_mode="all")
# 转换为 DTO
setting_items = [
SettingItem(type=s.type, name=s.name, value=s.value)
for s in settings
]
return SettingsListResponse(settings=setting_items, total=len(setting_items))
@admin_group_router.get( @admin_group_router.get(
path='/', path='/',