perf:优化webui配置展示,优化log显示,修复表达审核

This commit is contained in:
SengokuCola
2026-05-05 18:34:20 +08:00
parent 424287387a
commit 16de259955
13 changed files with 326 additions and 164 deletions

View File

@@ -78,7 +78,7 @@ class ChatManager:
"""初始化聊天管理器"""
try:
await self.load_all_sessions_from_db()
logger.info(f"已加载 {len(self.sessions)} 个会话记录到内存中")
logger.debug(f"已加载 {len(self.sessions)} 个会话记录到内存中")
except Exception as e:
logger.error(f"初始化聊天管理器出现错误: {e}")

View File

@@ -829,20 +829,19 @@ def initialize_logging(verbose: bool = True):
reconfigure_existing_loggers()
# 启动日志清理任务
start_log_cleanup_task(verbose=verbose)
start_log_cleanup_task()
# 只在 verbose=True 时输出详细的初始化信息
if verbose:
logger = get_logger("logger")
console_level = LOG_CONFIG.get("console_log_level", LOG_CONFIG.get("log_level", "INFO"))
file_level = LOG_CONFIG.get("file_log_level", LOG_CONFIG.get("log_level", "INFO"))
logger.info("日志系统已初始化:")
logger.info(f" - 控制台级别: {console_level}")
logger.info(f" - 文件级别: {file_level}")
max_log_files = max(1, int(LOG_CONFIG.get("max_log_files", 30) or 30))
log_cleanup_days = max(1, int(LOG_CONFIG.get("log_cleanup_days", 30) or 30))
logger.info(f" - 轮转份数: {max_log_files}个文件|自动清理: {log_cleanup_days}天前的日志")
logger.info(
f"日志系统已初始化:控制台={console_level},文件={file_level}"
f"轮转={max_log_files}个文件,清理={log_cleanup_days}天前"
)
def cleanup_old_logs():
@@ -875,12 +874,8 @@ def cleanup_old_logs():
logger.error(f"清理旧日志文件时出错: {e}")
def start_log_cleanup_task(verbose: bool = True):
"""启动日志清理任务
Args:
verbose: 是否输出启动信息。默认为 True。
"""
def start_log_cleanup_task():
"""启动日志清理任务"""
global _cleanup_task_started
# 防止重复启动清理任务
@@ -897,12 +892,6 @@ def start_log_cleanup_task(verbose: bool = True):
cleanup_thread = threading.Thread(target=cleanup_task, daemon=True)
cleanup_thread.start()
if verbose:
logger = get_logger("logger")
max_log_files = max(1, int(LOG_CONFIG.get("max_log_files", 30) or 30))
log_cleanup_days = max(1, int(LOG_CONFIG.get("log_cleanup_days", 30) or 30))
logger.info(f"已启动日志清理任务,将自动清理{log_cleanup_days}天前的日志文件(轮转份数限制: {max_log_files}个文件)")
def shutdown_logging():
"""优雅关闭日志系统,释放所有文件句柄"""

View File

@@ -40,6 +40,7 @@ class BotConfig(ConfigBase):
"x-icon": "wifi",
"x-layout": "inline-right",
"x-input-width": "12rem",
"x-row": "bot-platform-account",
},
)
"""平台"""
@@ -51,6 +52,7 @@ class BotConfig(ConfigBase):
"x-icon": "user",
"x-layout": "inline-right",
"x-input-width": "12rem",
"x-row": "bot-platform-account",
},
)
"""QQ账号"""

View File

@@ -134,7 +134,7 @@ def _setup_anti_crawler(app: FastAPI):
"basic": t("startup.webui_anti_crawler_mode_basic"),
}
mode_desc = mode_descriptions.get(anti_crawler_mode, t("startup.webui_anti_crawler_mode_basic"))
logger.info(t("startup.webui_anti_crawler_configured", mode_desc=mode_desc))
logger.debug(t("startup.webui_anti_crawler_configured", mode_desc=mode_desc))
except Exception as e:
logger.error(t("startup.webui_anti_crawler_config_failed", error=e), exc_info=True)
@@ -159,7 +159,7 @@ def _register_api_routes(app: FastAPI):
for router in get_all_routers():
app.include_router(router)
logger.info(t("startup.webui_api_routes_registered"))
logger.debug(t("startup.webui_api_routes_registered"))
except Exception as e:
logger.error(t("startup.webui_api_routes_register_failed", error=e), exc_info=True)
@@ -217,7 +217,7 @@ def _setup_static_files(app: FastAPI):
response.headers["X-Robots-Tag"] = "noindex, nofollow, noarchive"
return response
logger.info(t("startup.webui_static_files_configured", static_path=static_path))
logger.debug(t("startup.webui_static_files_configured", static_path=static_path))
def _resolve_static_path() -> Path | None:
@@ -247,6 +247,5 @@ def show_access_token():
token_manager = get_token_manager()
current_token = token_manager.get_token()
logger.info(t("startup.webui_access_token", token=current_token))
logger.info(t("startup.webui_access_token_login_hint"))
except Exception as e:
logger.error(t("startup.webui_access_token_failed", error=e))

View File

@@ -15,6 +15,7 @@ from src.common.logger import get_logger
from src.webui.dependencies import require_auth
logger = get_logger("webui.expression")
EXCLUDE_IDS_QUERY = Query(None, description="需要排除的表达方式 ID")
# 创建路由器
router = APIRouter(prefix="/expression", tags=["Expression"], dependencies=[Depends(require_auth)])
@@ -660,8 +661,10 @@ async def get_review_list(
page: int = Query(1, ge=1, description="页码"),
page_size: int = Query(20, ge=1, le=100, description="每页数量"),
filter_type: str = Query("unchecked", description="筛选类型: unchecked/passed/rejected/all"),
order: str = Query("latest", description="排序方式: latest/random"),
search: Optional[str] = Query(None, description="搜索关键词"),
chat_id: Optional[str] = Query(None, description="聊天ID筛选"),
exclude_ids: Optional[List[int]] = EXCLUDE_IDS_QUERY,
) -> ReviewListResponse:
"""获取待审核或已审核的表达方式列表。
@@ -669,8 +672,10 @@ async def get_review_list(
page: 页码。
page_size: 每页数量。
filter_type: 筛选类型,可选 unchecked、passed、rejected 或 all。
order: 排序方式,可选 latest 或 random。
search: 搜索关键词。
chat_id: 聊天 ID 筛选条件。
exclude_ids: 需要排除的表达方式 ID。
Returns:
ReviewListResponse: 审核列表响应。
@@ -689,11 +694,17 @@ async def get_review_list(
if chat_id:
statement = statement.where(col(Expression.session_id) == chat_id)
# 排序:创建时间倒序
statement = statement.order_by(
case((col(Expression.create_time).is_(None), 1), else_=0),
col(Expression.create_time).desc(),
)
if exclude_ids:
statement = statement.where(~col(Expression.id).in_(exclude_ids))
if order == "random":
statement = statement.order_by(func.random())
else:
# 排序:创建时间倒序
statement = statement.order_by(
case((col(Expression.create_time).is_(None), 1), else_=0),
col(Expression.create_time).desc(),
)
offset = (page - 1) * page_size
statement = statement.offset(offset).limit(page_size)
@@ -731,7 +742,7 @@ class BatchReviewItem(BaseModel):
id: int
rejected: bool
require_unchecked: bool = True # 默认要求未检查状态
require_unchecked: bool = True # 前端保留的来源标记,人工审核提交时不再阻断覆盖
class BatchReviewRequest(BaseModel):
@@ -790,14 +801,6 @@ async def batch_review_expressions(
failed += 1
continue
# 冲突检测:未审核列表发起的操作只允许处理仍处于未审核状态的条目。
if item.require_unchecked and expression.checked:
results.append(
BatchReviewResultItem(id=item.id, success=False, message="该表达方式已被审核,请刷新列表后重试")
)
failed += 1
continue
# 更新状态
with get_db_session() as session:
db_expression = session.exec(