WebUI 前端 & 后端超级大重构

This commit is contained in:
DrSmoothl
2026-03-14 21:06:36 +08:00
parent 6ca5a2939e
commit 172615f18a
69 changed files with 3128 additions and 6581 deletions

View File

@@ -76,7 +76,6 @@ MODULE_COLORS: Dict[str, Tuple[str, Optional[str], bool]] = {
"webui.jargon": ("#d7d75f", None, False),
"webui.person": ("#87d787", None, False),
"webui.statistics": ("#af87ff", None, False),
"webui.annual_report": ("#ffaf87", None, False),
"webui.plugin_routes": ("#ffaf00", None, False),
"webui.plugin_progress": ("#ff8700", None, False),
"webui.git_mirror": ("#878787", None, False),
@@ -180,7 +179,6 @@ MODULE_ALIASES = {
"webui.jargon": "WebUI黑话",
"webui.person": "WebUI人物",
"webui.statistics": "WebUI统计",
"webui.annual_report": "WebUI年报",
"webui.plugin_routes": "WebUI插件",
"webui.plugin_progress": "WebUI插件进度",
"webui.git_mirror": "WebUI镜像",

View File

@@ -1,6 +1,5 @@
import traceback
from datetime import datetime
from types import SimpleNamespace
from typing import Any
import json
@@ -48,48 +47,8 @@ def _parse_additional_config(message: Messages) -> dict[str, Any]:
return {}
def _normalize_optional_str(value: object) -> str | None:
if value is None:
return None
if isinstance(value, str):
return value
try:
return json.dumps(value, ensure_ascii=False)
except (TypeError, ValueError):
return str(value)
def _message_to_instance(message: Messages) -> SessionMessage:
config = _parse_additional_config(message)
instance = SessionMessage.from_db_instance(message)
instance.interest_value = config.get("interest_value")
instance.key_words = _normalize_optional_str(config.get("key_words"))
instance.key_words_lite = _normalize_optional_str(config.get("key_words_lite"))
instance.reply_probability_boost = config.get("reply_probability_boost")
instance.priority_mode = _normalize_optional_str(config.get("priority_mode"))
instance.priority_info = _normalize_optional_str(config.get("priority_info"))
instance.intercept_message_level = config.get("intercept_message_level", 0)
instance.selected_expressions = _normalize_optional_str(config.get("selected_expressions"))
group_info = instance.message_info.group_info
legacy_group_info = None
if group_info:
legacy_group_info = SimpleNamespace(
group_id=group_info.group_id,
group_name=group_info.group_name,
)
instance.user_info = SimpleNamespace(
user_id=instance.message_info.user_info.user_id,
user_nickname=instance.message_info.user_info.user_nickname,
user_cardname=instance.message_info.user_info.user_cardname,
platform=instance.platform,
)
instance.chat_info = SimpleNamespace(
platform=instance.platform,
stream_id=instance.session_id,
group_info=legacy_group_info,
)
instance.time = instance.timestamp.timestamp()
return instance
return SessionMessage.from_db_instance(message)
def _coerce_datetime(value: Any) -> Any:
@@ -118,6 +77,7 @@ def _build_message_conditions(
end_time: float | None = None,
before_time: float | None = None,
after_time: float | None = None,
has_reply_to: bool | None = None,
) -> list[Any]:
conditions: list[Any] = [Messages.message_id != "notice"]
@@ -141,6 +101,10 @@ def _build_message_conditions(
conditions.append(Messages.timestamp < _coerce_datetime(before_time))
if after_time is not None:
conditions.append(Messages.timestamp > _coerce_datetime(after_time))
if has_reply_to is True:
conditions.append(col(Messages.reply_to).is_not(None))
elif has_reply_to is False:
conditions.append(col(Messages.reply_to).is_(None))
return conditions
@@ -261,6 +225,7 @@ def count_messages(
end_time: float | None = None,
before_time: float | None = None,
after_time: float | None = None,
has_reply_to: bool | None = None,
) -> int:
"""
根据提供的过滤器计算消息数量。
@@ -276,6 +241,7 @@ def count_messages(
end_time: 结束时间,闭区间上界。
before_time: 严格早于该时间。
after_time: 严格晚于该时间。
has_reply_to: 是否要求存在 reply_to 字段。
Returns:
符合条件的消息数量,如果出错则返回 0。
@@ -292,6 +258,7 @@ def count_messages(
end_time=end_time,
before_time=before_time,
after_time=after_time,
has_reply_to=has_reply_to,
)
statement = select(func.count()).select_from(Messages).where(*conditions)
with get_db_session() as session:
@@ -302,7 +269,7 @@ def count_messages(
"使用 SQLModel 计数消息失败 "
f"(session_id={session_id}, user_id={user_id}, group_id={group_id}, platform={platform}, "
f"message_id={message_id}, reply_to={reply_to}, start_time={start_time}, end_time={end_time}, "
f"before_time={before_time}, after_time={after_time}): {e}\n{traceback.format_exc()}"
f"before_time={before_time}, after_time={after_time}, has_reply_to={has_reply_to}): {e}\n{traceback.format_exc()}"
)
logger.error(log_message)
return 0

View File

@@ -25,13 +25,15 @@ def is_port_conflict_error(error: OSError) -> bool:
return "address already in use" in message or "已被占用" in message
def check_port_available(host: str, port: int) -> bool:
def check_port_available(host: str, port: int, *, allow_reuse_addr: bool = False) -> bool:
family = _detect_socket_family(host)
test_host = _normalize_test_host(host)
try:
with socket.socket(family, socket.SOCK_STREAM) as test_socket:
test_socket.settimeout(1)
if allow_reuse_addr:
test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
test_socket.bind((test_host, port))
return True
except OSError:
@@ -65,8 +67,9 @@ def assert_port_available(
service_name: str,
logger,
config_hint: Optional[str] = None,
allow_reuse_addr: bool = False,
) -> None:
if check_port_available(host=host, port=port):
if check_port_available(host=host, port=port, allow_reuse_addr=allow_reuse_addr):
return
log_port_conflict(