diff --git a/zhenxun/builtin_plugins/plugin_store/data_source.py b/zhenxun/builtin_plugins/plugin_store/data_source.py index a7332f4d..f465411d 100644 --- a/zhenxun/builtin_plugins/plugin_store/data_source.py +++ b/zhenxun/builtin_plugins/plugin_store/data_source.py @@ -219,7 +219,7 @@ class StoreManager: return plugin_info, is_external @classmethod - async def add_plugin(cls, index_or_module: str, source: str | None) -> str: + async def add_plugin(cls, index_or_module: str, source: str | None = None) -> str: """添加插件 参数: @@ -518,11 +518,11 @@ class StoreManager: raise PluginStoreException("插件ID不存在...") return all_plugin_list[idx].module elif isinstance(plugin_id, str): - result = ( - None - if plugin_id not in [v.module for v in all_plugin_list] - else plugin_id - ) or next(v for v in all_plugin_list if v.name == plugin_id).module - if not result: - raise PluginStoreException("插件 Module / 名称 不存在...") - return result + if plugin_id in [v.module for v in all_plugin_list]: + return plugin_id + + for plugin_info in all_plugin_list: + if plugin_info.name.lower() == plugin_id.lower(): + return plugin_info.module + + raise PluginStoreException("插件 Module / 名称 不存在...") diff --git a/zhenxun/builtin_plugins/web_ui/api/tabs/main/__init__.py b/zhenxun/builtin_plugins/web_ui/api/tabs/main/__init__.py index f93d0ab1..36059101 100644 --- a/zhenxun/builtin_plugins/web_ui/api/tabs/main/__init__.py +++ b/zhenxun/builtin_plugins/web_ui/api/tabs/main/__init__.py @@ -16,7 +16,7 @@ from zhenxun.utils.platform import PlatformUtils from ....base_model import Result from ....config import QueryDateType -from ....utils import authentication, clear_help_image, get_system_status +from ....utils import authentication, get_system_status from .data_source import ApiDataSource from .model import ( ActiveGroup, @@ -234,7 +234,6 @@ async def _(param: BotManageUpdateParam): bot_data.block_plugins = CommonUtils.convert_module_format(param.block_plugins) bot_data.block_tasks = CommonUtils.convert_module_format(param.block_tasks) await bot_data.save(update_fields=["block_plugins", "block_tasks"]) - clear_help_image() return Result.ok() except Exception as e: logger.error(f"{router.prefix}/update_bot_manage 调用错误", "WebUi", e=e) diff --git a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py index 1e0d5a50..bd4553ba 100644 --- a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py +++ b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py @@ -7,7 +7,7 @@ from zhenxun.utils.enum import BlockType, PluginType from zhenxun.utils.manager.virtual_env_package_manager import VirtualEnvPackageManager from ....base_model import Result -from ....utils import authentication, clear_help_image +from ....utils import authentication from .data_source import ApiDataSource from .model import ( BatchUpdatePlugins, @@ -82,7 +82,6 @@ async def _() -> Result[PluginCount]: async def _(param: UpdatePlugin) -> Result: try: await ApiDataSource.update_plugin(param) - clear_help_image() return Result.ok(info="已经帮你写好啦!") except (ValueError, KeyError): return Result.fail("插件数据不存在...") @@ -110,7 +109,6 @@ async def _(param: PluginSwitch) -> Result: db_plugin.block_type = None db_plugin.status = True await db_plugin.save() - clear_help_image() return Result.ok(info="成功改变了开关状态!") except Exception as e: logger.error(f"{router.prefix}/change_switch 调用错误", "WebUi", e=e) @@ -177,7 +175,6 @@ async def _( updated_count=result_dict["updated_count"], errors=result_dict["errors"], ) - clear_help_image() return Result.ok(result_model, "插件配置更新完成") except Exception as e: logger.error(f"{router.prefix}/plugins/batch_update 调用错误", "WebUi", e=e) @@ -197,7 +194,6 @@ async def _(payload: RenameMenuTypePayload) -> Result[str]: old_name=payload.old_name, new_name=payload.new_name ) if result.get("success"): - clear_help_image() return Result.ok( info=result.get( "info", diff --git a/zhenxun/builtin_plugins/web_ui/utils.py b/zhenxun/builtin_plugins/web_ui/utils.py index 84459114..9ff803e9 100644 --- a/zhenxun/builtin_plugins/web_ui/utils.py +++ b/zhenxun/builtin_plugins/web_ui/utils.py @@ -12,7 +12,7 @@ import psutil import ujson as json from zhenxun.configs.config import Config -from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH +from zhenxun.configs.path_config import DATA_PATH from .base_model import SystemFolderSize, SystemStatus, User @@ -68,22 +68,6 @@ def validate_path(path_str: str | None) -> tuple[Path | None, str | None]: return None, f"路径验证失败: {e!s}" -GROUP_HELP_PATH = DATA_PATH / "group_help" -SIMPLE_HELP_IMAGE = IMAGE_PATH / "SIMPLE_HELP.png" -SIMPLE_DETAIL_HELP_IMAGE = IMAGE_PATH / "SIMPLE_DETAIL_HELP.png" - - -def clear_help_image(): - """清理帮助图片""" - if SIMPLE_HELP_IMAGE.exists(): - SIMPLE_HELP_IMAGE.unlink() - if SIMPLE_DETAIL_HELP_IMAGE.exists(): - SIMPLE_DETAIL_HELP_IMAGE.unlink() - for file in GROUP_HELP_PATH.iterdir(): - if file.is_file(): - file.unlink() - - def get_user(uname: str) -> User | None: """获取账号密码 diff --git a/zhenxun/models/ban_console.py b/zhenxun/models/ban_console.py index b1c6a4d9..4fec9608 100644 --- a/zhenxun/models/ban_console.py +++ b/zhenxun/models/ban_console.py @@ -4,6 +4,7 @@ from typing_extensions import Self from tortoise import fields +from zhenxun.services.data_access import DataAccess from zhenxun.services.db_context import Model from zhenxun.services.log import logger from zhenxun.utils.enum import CacheType, DbLockType @@ -57,14 +58,15 @@ class BanConsole(Model): """ if not user_id and not group_id: raise UserAndGroupIsNone() + dao = DataAccess(cls) if user_id: return ( - await cls.safe_get_or_none(user_id=user_id, group_id=group_id) + await dao.safe_get_or_none(user_id=user_id, group_id=group_id) if group_id - else await cls.safe_get_or_none(user_id=user_id, group_id__isnull=True) + else await dao.safe_get_or_none(user_id=user_id, group_id__isnull=True) ) else: - return await cls.safe_get_or_none(user_id="", group_id=group_id) + return await dao.safe_get_or_none(user_id="", group_id=group_id) @classmethod async def check_ban_level( diff --git a/zhenxun/models/group_console.py b/zhenxun/models/group_console.py index ad36dccd..e73c4cde 100644 --- a/zhenxun/models/group_console.py +++ b/zhenxun/models/group_console.py @@ -7,6 +7,7 @@ from tortoise.backends.base.client import BaseDBAsyncClient from zhenxun.models.plugin_info import PluginInfo from zhenxun.models.task_info import TaskInfo from zhenxun.services.cache import CacheRoot +from zhenxun.services.data_access import DataAccess from zhenxun.services.db_context import Model from zhenxun.utils.enum import CacheType, DbLockType, PluginType @@ -254,13 +255,14 @@ class GroupConsole(Model): 返回: Self: GroupConsole """ + dao = DataAccess(cls) if channel_id: - return await cls.safe_get_or_none( + return await dao.safe_get_or_none( group_id=group_id, channel_id=channel_id, clean_duplicates=clean_duplicates, ) - return await cls.safe_get_or_none( + return await dao.safe_get_or_none( group_id=group_id, channel_id__isnull=True, clean_duplicates=clean_duplicates, diff --git a/zhenxun/services/cache/cache_containers.py b/zhenxun/services/cache/cache_containers.py index 098d03f9..4302a747 100644 --- a/zhenxun/services/cache/cache_containers.py +++ b/zhenxun/services/cache/cache_containers.py @@ -37,7 +37,7 @@ class CacheDict(Generic[T]): return 0 return data.expire_time - def __getitem__(self, key: str) -> T | None: + def __getitem__(self, key: str) -> T: """获取字典项 参数: @@ -47,8 +47,10 @@ class CacheDict(Generic[T]): T: 字典值 """ if value := self._data.get(key): - return value.value if self.expire_time(key) else None - return None + if self.expire_time(key): + raise KeyError(f"键 {key} 已过期") + return value.value + raise KeyError(f"键 {key} 不存在") def __setitem__(self, key: str, value: T) -> None: """设置字典项 diff --git a/zhenxun/services/data_access.py b/zhenxun/services/data_access.py index a4ebd28b..3912fe28 100644 --- a/zhenxun/services/data_access.py +++ b/zhenxun/services/data_access.py @@ -7,6 +7,8 @@ from zhenxun.services.log import logger T = TypeVar("T", bound=Model) +cache = CacheRoot.cache_dict("DB_TEST_BAN", 10, int) + class DataAccess(Generic[T]): """数据访问层,根据配置决定是否使用缓存 @@ -167,6 +169,7 @@ class DataAccess(Generic[T]): return await with_db_timeout( db_query_func(*args, **kwargs), operation=f"{self.model_cls.__name__}.{db_query_func.__name__}", + source="DataAccess", ) # 尝试从缓存获取 @@ -179,9 +182,10 @@ class DataAccess(Generic[T]): if cache_key is not None: data = await self.cache.get(cache_key) logger.debug( - f"{self.model_cls.__name__} self.cache.get(cache_key)" + f"{self.model_cls.__name__} key: {cache_key}" f" 从缓存获取到的数据 {type(data)}: {data}" ) + if data == self._NULL_RESULT: # 空结果缓存命中 self._cache_stats[self.cache_type]["null_hits"] += 1 diff --git a/zhenxun/services/db_context/base_model.py b/zhenxun/services/db_context/base_model.py index 3e0e23ef..ff642258 100644 --- a/zhenxun/services/db_context/base_model.py +++ b/zhenxun/services/db_context/base_model.py @@ -227,6 +227,7 @@ class Model(TortoiseModel): return await with_db_timeout( cls.get_or_none(*args, using_db=using_db, **kwargs), operation=f"{cls.__name__}.get_or_none", + source="DataBaseModel", ) except MultipleObjectsReturned: # 如果出现多个记录的情况,进行特殊处理 @@ -239,6 +240,7 @@ class Model(TortoiseModel): records = await with_db_timeout( cls.filter(*args, **kwargs).all(), operation=f"{cls.__name__}.filter.all", + source="DataBaseModel", ) if not records: @@ -255,6 +257,7 @@ class Model(TortoiseModel): await with_db_timeout( record.delete(), operation=f"{cls.__name__}.delete_duplicate", + source="DataBaseModel", ) logger.info( f"{cls.__name__} 删除重复记录:" @@ -269,11 +272,13 @@ class Model(TortoiseModel): return await with_db_timeout( cls.filter(*args, **kwargs).order_by("-id").first(), operation=f"{cls.__name__}.filter.order_by.first", + source="DataBaseModel", ) # 如果没有 id 字段,则返回第一个记录 return await with_db_timeout( cls.filter(*args, **kwargs).first(), operation=f"{cls.__name__}.filter.first", + source="DataBaseModel", ) except asyncio.TimeoutError: logger.error( diff --git a/zhenxun/services/db_context/utils.py b/zhenxun/services/db_context/utils.py index 47db548f..d0f58a1e 100644 --- a/zhenxun/services/db_context/utils.py +++ b/zhenxun/services/db_context/utils.py @@ -11,11 +11,15 @@ from .config import ( async def with_db_timeout( - coro, timeout: float = DB_TIMEOUT_SECONDS, operation: str | None = None + coro, + timeout: float = DB_TIMEOUT_SECONDS, + operation: str | None = None, + source: str | None = None, ): """带超时控制的数据库操作""" start_time = time.time() try: + logger.debug(f"开始执行数据库操作: {operation} 来源: {source}") result = await asyncio.wait_for(coro, timeout=timeout) elapsed = time.time() - start_time if elapsed > SLOW_QUERY_THRESHOLD and operation: diff --git a/zhenxun/utils/manager/zhenxun_repo_manager.py b/zhenxun/utils/manager/zhenxun_repo_manager.py index ecae4669..ac157da9 100644 --- a/zhenxun/utils/manager/zhenxun_repo_manager.py +++ b/zhenxun/utils/manager/zhenxun_repo_manager.py @@ -50,6 +50,7 @@ class ZhenxunRepoConfig: "zhenxun/utils", "zhenxun/models", "zhenxun/configs", + "zhenxun/ui", ] ZHENXUN_BOT_VERSION_FILE_STRING = "__version__" ZHENXUN_BOT_VERSION_FILE = Path() / ZHENXUN_BOT_VERSION_FILE_STRING