From 55401d0df7279120b21ac625f38ea25fa4842c53 Mon Sep 17 00:00:00 2001 From: KimigaiiWuyi <444835641@qq.com> Date: Sun, 4 May 2025 06:25:25 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20=E7=BD=91=E9=A1=B5=E6=8E=A7?= =?UTF-8?q?=E5=88=B6=E5=8F=B0=E9=85=8D=E7=BD=AE=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gsuid_core/core.py | 5 +- gsuid_core/web_app.py | 4 - gsuid_core/webconsole/gs_data.py | 83 +++++++++++++++++ gsuid_core/webconsole/html.py | 5 ++ gsuid_core/webconsole/mount_app.py | 140 ++++++++++++++++------------- gsuid_core/webconsole/page.html | 9 ++ 6 files changed, 178 insertions(+), 68 deletions(-) create mode 100644 gsuid_core/webconsole/gs_data.py diff --git a/gsuid_core/core.py b/gsuid_core/core.py index 3de29d5..55012f5 100644 --- a/gsuid_core/core.py +++ b/gsuid_core/core.py @@ -14,8 +14,8 @@ sys.path.append(str(Path(__file__).resolve().parents[1])) from gsuid_core.gss import gss # noqa: E402 from gsuid_core.bot import _Bot # noqa: E402 -from gsuid_core.web_app import app # noqa: E402 from gsuid_core.logger import logger # noqa: E402 +from gsuid_core.web_app import app, site # noqa: E402 from gsuid_core.config import core_config # noqa: E402 from gsuid_core.handler import handle_event # noqa: E402 from gsuid_core.models import MessageReceive # noqa: E402 @@ -100,6 +100,9 @@ def main(): else: return {'status_code': -100, 'data': None} + site.gen_plugin_page() + site.mount_app(app) + uvicorn.run( app, host=HOST, diff --git a/gsuid_core/web_app.py b/gsuid_core/web_app.py index 9371f15..96cf250 100644 --- a/gsuid_core/web_app.py +++ b/gsuid_core/web_app.py @@ -625,7 +625,3 @@ async def get_history_logs( 'rows': log_file, }, } - - -site.mount_app(app) -site.mount_app(app) diff --git a/gsuid_core/webconsole/gs_data.py b/gsuid_core/webconsole/gs_data.py new file mode 100644 index 0000000..6f2ed46 --- /dev/null +++ b/gsuid_core/webconsole/gs_data.py @@ -0,0 +1,83 @@ +from fastapi_amis_admin import admin + +from gsuid_core.webconsole.mount_app import PageSchema, GsAdminModel, site +from gsuid_core.utils.database.models import ( + GsBind, + GsPush, + GsUser, + GsCache, + Subscribe, +) + + +class CKAdmin(GsAdminModel): + pk_name = 'id' + page_schema = PageSchema( + label='CK管理', + icon='fa fa-database', + ) # type: ignore + + # 配置管理模型 + model = GsUser + + +class PushAdmin(GsAdminModel): + pk_name = 'id' + page_schema = PageSchema( + label='推送管理', + icon='fa fa-bullhorn', + ) # type: ignore + + # 配置管理模型 + model = GsPush + + +class CacheAdmin(GsAdminModel): + pk_name = 'id' + page_schema = PageSchema( + label='缓存管理', + icon='fa fa-recycle', + ) # type: ignore + + # 配置管理模型 + model = GsCache + + +class BindAdmin(GsAdminModel): + pk_name = 'id' + page_schema = PageSchema( + label='绑定管理', + icon='fa fa-users', + ) # type: ignore + + # 配置管理模型 + model = GsBind + + +@site.register_admin +class MiHoYoDatabase(admin.AdminApp): + page_schema = PageSchema( + label="米游数据库", + icon="fa fa-database", + ) # type: ignore + + def __init__(self, app: "admin.AdminApp"): + super().__init__(app) + self.register_admin( + CKAdmin, + PushAdmin, + CacheAdmin, + BindAdmin, + ) + + +@site.register_admin +class SubscribeAdmin(GsAdminModel): + pk_name = 'id' + page_schema = PageSchema( + label='订阅管理', + icon='fa fa-rss', + ) # type: ignore + + # 配置管理模型 + model = Subscribe diff --git a/gsuid_core/webconsole/html.py b/gsuid_core/webconsole/html.py index fb5c41d..2a0c01d 100644 --- a/gsuid_core/webconsole/html.py +++ b/gsuid_core/webconsole/html.py @@ -4,6 +4,7 @@ from gsuid_core.version import __version__ as gscore_version bots = 'HoshinoBot · NoneBot2 · Koishi · Yunzai · ZeroBot · AstrBot' sup = f'✨支持连接{bots}的多功能Bot插件核心✨' + style = ''' div { background: rgba(255, 255, 255, 0.6) url('/webstatic/bg.jpg'); @@ -80,6 +81,10 @@ rect { } */ +.amis-scope .a-TextControl .InputText-clear { + background-color: #ffffff; +} + .amis-scope .a-Layout-brand, .amis-scope .a-Layout-brandBar, .amis-scope .a-Layout-aside { background-color: rgba(0, 0, 0, 0); } diff --git a/gsuid_core/webconsole/mount_app.py b/gsuid_core/webconsole/mount_app.py index b71d89d..a04a761 100644 --- a/gsuid_core/webconsole/mount_app.py +++ b/gsuid_core/webconsole/mount_app.py @@ -1,7 +1,9 @@ # flake8: noqa +import os +import inspect import platform from pathlib import Path -from typing import Any, Dict, List, Callable +from typing import Any, Dict, List, Type, Callable from starlette import status from pydantic import BaseModel @@ -15,6 +17,7 @@ from fastapi_amis_admin.models.fields import Field from fastapi import Depends, Request, HTTPException from fastapi_user_auth.admin.app import UserAuthApp from sqlalchemy.sql.elements import BinaryExpression +from fastapi_amis_admin.admin.admin import BaseAdminT from fastapi_amis_admin.admin.settings import Settings from fastapi_user_auth.admin.site import AuthAdminSite from fastapi_amis_admin.utils.translation import i18n as _ @@ -55,13 +58,6 @@ from gsuid_core.webconsole.create_analysis_panel import get_analysis_page from gsuid_core.webconsole.create_history_log import get_history_logs_page from gsuid_core.webconsole.create_batch_push_panel import get_batch_push_panel from gsuid_core.webconsole.create_core_config_panel import get_core_config_page -from gsuid_core.utils.database.models import ( - GsBind, - GsPush, - GsUser, - GsCache, - Subscribe, -) from gsuid_core.webconsole.login_page import ( # noqa # 不要删 AuthRouter, amis_admin, @@ -188,6 +184,53 @@ settings = Settings( ) +def get_caller_plugin_name(): + # 获取调用栈 + stack = inspect.stack() + + caller_frame = stack[2] + + caller_file = caller_frame.filename + caller_path = os.path.abspath(caller_file) + caller_path = Path(caller_path) + + parts = caller_path.parts + matches = [] + for i in range(len(parts) - 1): + if parts[i] == "gsuid_core" and parts[i + 1] == "plugins": + matches.append(i) + + # 如果没有匹配,返回 None + if not matches: + return None + + # 取最后一个匹配(最深层) + last_match = matches[-1] + + # 提取 plugins 下一级目录或文件名 + if len(parts) > last_match + 2: # 确保有下一级 + return parts[last_match + 2] + + return None + + +def create_admin_class(class_name: str, label: str, admin_list: List): + + def __init__(self, app: "admin.AdminApp"): + super(self.__class__, self).__init__(app) + self.register_admin(*admin_list) + + # 构建类的属性字典 + attrs = { + "page_schema": PageSchema(label=label, icon='fa fa-plus'), # type: ignore + "__init__": __init__, + } + + NewAdminClass = type(class_name, (admin.AdminApp,), attrs) + + return NewAdminClass + + # 自定义后台管理站点 class GsAdminSite(GsAuthAdminSite): template_name = str(Path(__file__).parent / 'page.html') @@ -199,6 +242,8 @@ class GsAdminSite(GsAuthAdminSite): super().__init__(settings) self.auth = self.auth or Auth(db=self.db) self.register_admin(self.UserAuthApp) + self.plugins_page: Dict[str, List] = {} + self.is_start = False async def get_page(self, request: Request) -> App: app = await super().get_page(request) @@ -206,6 +251,30 @@ class GsAdminSite(GsAuthAdminSite): app.logo = 'https://s2.loli.net/2022/01/31/kwCIl3cF1Z2GxnR.png' return app + def register_admin( + self, *admin_cls: Type[BaseAdminT], _ADD: bool = False + ) -> Type[BaseAdminT]: + plugin_name = get_caller_plugin_name() + if plugin_name and not _ADD: + if plugin_name not in self.plugins_page: + self.plugins_page[plugin_name] = [] + self.plugins_page[plugin_name].extend(admin_cls) + else: + [self._registered.update({cls: None}) for cls in admin_cls if cls] + return admin_cls[0] + + def gen_plugin_page(self): + if not self.is_start: + self.is_start = True + for plugin_name, admin_cls in self.plugins_page.items(): + cls = create_admin_class( + f'{plugin_name}App', + plugin_name.replace('UID', ''), + admin_cls, + ) + self.register_admin(cls, _ADD=True) + self.get_admin_or_create(cls) + site = GsAdminSite(settings) site.auth.user_model = User @@ -461,52 +530,6 @@ class LogAndMessage(admin.AdminApp): ) -class CKAdmin(GsAdminModel): - pk_name = 'id' - page_schema = PageSchema(label='CK管理', icon='fa fa-database') # type: ignore - - # 配置管理模型 - model = GsUser - - -class PushAdmin(GsAdminModel): - pk_name = 'id' - page_schema = PageSchema(label='推送管理', icon='fa fa-bullhorn') # type: ignore - - # 配置管理模型 - model = GsPush - - -class CacheAdmin(GsAdminModel): - pk_name = 'id' - page_schema = PageSchema(label='缓存管理', icon='fa fa-recycle') # type: ignore - - # 配置管理模型 - model = GsCache - - -class BindAdmin(GsAdminModel): - pk_name = 'id' - page_schema = PageSchema(label='绑定管理', icon='fa fa-users') # type: ignore - - # 配置管理模型 - model = GsBind - - -@site.register_admin -class MiHoYoDatabase(admin.AdminApp): - page_schema = PageSchema(label="米游数据库", icon="fa fa-database") # type: ignore - - def __init__(self, app: "admin.AdminApp"): - super().__init__(app) - self.register_admin( - CKAdmin, - PushAdmin, - CacheAdmin, - BindAdmin, - ) - - class AmisPageAdmin(admin.PageAdmin): page_schema = '入门使用' @@ -607,14 +630,5 @@ class MiHoYoBind(admin.AdminApp): ) -@site.register_admin -class SubscribeAdmin(GsAdminModel): - pk_name = 'id' - page_schema = PageSchema(label='订阅管理', icon='fa fa-rss') # type: ignore - - # 配置管理模型 - model = Subscribe - - # 取消注册默认管理类 site.unregister_admin(admin.HomeAdmin, APIDocsApp, FileAdmin) diff --git a/gsuid_core/webconsole/page.html b/gsuid_core/webconsole/page.html index 0a6163b..320b1d0 100644 --- a/gsuid_core/webconsole/page.html +++ b/gsuid_core/webconsole/page.html @@ -219,6 +219,15 @@ overflow: hidden; } + .amis-scope .a-Layout--asideFixed .a-Layout-aside { + width: 15%; + border: 1px solid #ce5050; + } + + .amis-scope .a-TextControl .InputText-clear { + background-color: #ffffff; + } +