mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-01 17:49:58 +08:00
重构webui适配 (#1801)
* ♻️ 使用Uninfo重构PlatformUtils基础方法 * 🩹 优化插件加载与模块格式转换逻辑 * 🚑 修复商店道具无法使用 * 🚑 修复道具无法正常使用 * 🔧 增加Bot状态管理及模块禁用功能 * 🎨 优化Web UI代码结构,修改target方法 * 🚨 auto fix by pre-commit hooks * 🎨 添加菜单API及优化异常处理 * 🐛 优化菜单API及模型结构,修复WebUi插件列表Api * 📝 更新仓库readme * 🚨 add mdlint file * 📝 Add help chapter. * 🐛 修复优化AuthChecker逻辑 * 🐛 优化数据库API,移除冗余导入及修正SQL_DICT引用 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: BalconyJH <balconyjh@gmail.com>
This commit is contained in:
co-authored by
pre-commit-ci[bot]
BalconyJH
parent
ebf05fd884
commit
35014e4048
@@ -3,14 +3,15 @@ from fastapi.responses import JSONResponse
|
||||
import nonebot
|
||||
from nonebot.drivers import Driver
|
||||
from tortoise import Tortoise
|
||||
from tortoise.exceptions import OperationalError
|
||||
|
||||
from zhenxun.configs.config import BotConfig
|
||||
from zhenxun.models.plugin_info import PluginInfo
|
||||
from zhenxun.models.task_info import TaskInfo
|
||||
from zhenxun.services.log import logger
|
||||
|
||||
from ....base_model import BaseResultModel, QueryModel, Result
|
||||
from ....utils import authentication
|
||||
from .data_source import ApiDataSource, type2sql
|
||||
from .models.model import Column, SqlModel, SqlText
|
||||
from .models.sql_log import SqlLog
|
||||
|
||||
@@ -20,52 +21,6 @@ router = APIRouter(prefix="/database")
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
|
||||
SQL_DICT = {}
|
||||
|
||||
|
||||
SELECT_TABLE_MYSQL_SQL = """
|
||||
SELECT table_name AS name, table_comment AS `desc`
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = DATABASE();
|
||||
"""
|
||||
|
||||
SELECT_TABLE_SQLITE_SQL = """
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
"""
|
||||
|
||||
SELECT_TABLE_PSQL_SQL = """
|
||||
select a.tablename as name,d.description as desc from pg_tables a
|
||||
left join pg_class c on relname=tablename
|
||||
left join pg_description d on oid=objoid and objsubid=0 where a.schemaname='public'
|
||||
"""
|
||||
|
||||
SELECT_TABLE_COLUMN_PSQL_SQL = """
|
||||
SELECT column_name, data_type, character_maximum_length as max_length, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = '{}';
|
||||
"""
|
||||
|
||||
SELECT_TABLE_COLUMN_MYSQL_SQL = """
|
||||
SHOW COLUMNS FROM {};
|
||||
"""
|
||||
|
||||
SELECT_TABLE_COLUMN_SQLITE_SQL = """
|
||||
PRAGMA table_info({});
|
||||
"""
|
||||
|
||||
type2sql = {
|
||||
"mysql": SELECT_TABLE_MYSQL_SQL,
|
||||
"sqlite": SELECT_TABLE_SQLITE_SQL,
|
||||
"postgres": SELECT_TABLE_PSQL_SQL,
|
||||
}
|
||||
|
||||
type2sql_column = {
|
||||
"mysql": SELECT_TABLE_COLUMN_MYSQL_SQL,
|
||||
"sqlite": SELECT_TABLE_COLUMN_SQLITE_SQL,
|
||||
"postgres": SELECT_TABLE_COLUMN_PSQL_SQL,
|
||||
}
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
for plugin in nonebot.get_loaded_plugins():
|
||||
@@ -73,7 +28,7 @@ async def _():
|
||||
sql_list = []
|
||||
if plugin.metadata and plugin.metadata.extra:
|
||||
sql_list = plugin.metadata.extra.get("sql_list")
|
||||
if module in SQL_DICT:
|
||||
if module in ApiDataSource.SQL_DICT:
|
||||
raise ValueError(f"{module} 常用SQL module 重复")
|
||||
if sql_list:
|
||||
SqlModel(
|
||||
@@ -81,15 +36,15 @@ async def _():
|
||||
module=module,
|
||||
sql_list=sql_list,
|
||||
)
|
||||
SQL_DICT[module] = SqlModel
|
||||
if SQL_DICT:
|
||||
result = await PluginInfo.filter(module__in=SQL_DICT.keys()).values_list(
|
||||
"module", "name"
|
||||
)
|
||||
ApiDataSource.SQL_DICT[module] = SqlModel
|
||||
if ApiDataSource.SQL_DICT:
|
||||
result = await PluginInfo.filter(
|
||||
module__in=ApiDataSource.SQL_DICT.keys()
|
||||
).values_list("module", "name")
|
||||
module2name = {r[0]: r[1] for r in result}
|
||||
for s in SQL_DICT:
|
||||
module = SQL_DICT[s].module
|
||||
SQL_DICT[s].name = module2name.get(module, module)
|
||||
for s in ApiDataSource.SQL_DICT:
|
||||
module = ApiDataSource.SQL_DICT[s].module
|
||||
ApiDataSource.SQL_DICT[s].name = module2name.get(module, module)
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -100,10 +55,14 @@ async def _():
|
||||
description="获取数据库表",
|
||||
)
|
||||
async def _() -> Result[list[dict]]:
|
||||
db = Tortoise.get_connection("default")
|
||||
sql_type = BotConfig.get_sql_type()
|
||||
query = await db.execute_query_dict(type2sql[sql_type])
|
||||
return Result.ok(query)
|
||||
try:
|
||||
db = Tortoise.get_connection("default")
|
||||
sql_type = BotConfig.get_sql_type()
|
||||
query = await db.execute_query_dict(type2sql[sql_type])
|
||||
return Result.ok(query)
|
||||
except Exception as e:
|
||||
logger.error(f"{router.prefix}/get_table_list 调用错误", "WebUi", e=e)
|
||||
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -114,34 +73,13 @@ async def _() -> Result[list[dict]]:
|
||||
description="获取表字段",
|
||||
)
|
||||
async def _(table_name: str) -> Result[list[Column]]:
|
||||
db = Tortoise.get_connection("default")
|
||||
sql_type = BotConfig.get_sql_type()
|
||||
sql = type2sql_column[sql_type]
|
||||
query = await db.execute_query_dict(sql.format(table_name))
|
||||
result_list = []
|
||||
if sql_type == "sqlite":
|
||||
result_list.extend(
|
||||
Column(
|
||||
column_name=result["name"],
|
||||
data_type=result["type"],
|
||||
max_length=-1,
|
||||
is_nullable="YES" if result["notnull"] == 1 else "NO",
|
||||
)
|
||||
for result in query
|
||||
try:
|
||||
return Result.ok(
|
||||
await ApiDataSource.get_table_column(table_name), "拿到信息啦!"
|
||||
)
|
||||
elif sql_type == "mysql":
|
||||
result_list.extend(
|
||||
Column(
|
||||
column_name=result["Field"],
|
||||
data_type=result["Type"],
|
||||
max_length=-1,
|
||||
is_nullable=result["Null"],
|
||||
)
|
||||
for result in query
|
||||
)
|
||||
else:
|
||||
result_list.extend(Column(**result) for result in query)
|
||||
return Result.ok(result_list)
|
||||
except Exception as e:
|
||||
logger.error(f"{router.prefix}/get_table_column 调用错误", "WebUi", e=e)
|
||||
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
|
||||
|
||||
|
||||
@router.post(
|
||||
@@ -163,7 +101,8 @@ async def _(sql: SqlText, request: Request) -> Result[list[dict]]:
|
||||
result = await TaskInfo.raw(sql.sql)
|
||||
await SqlLog.add(ip or "0.0.0.0", sql.sql, str(result))
|
||||
return Result.ok(info="执行成功啦!")
|
||||
except OperationalError as e:
|
||||
except Exception as e:
|
||||
logger.error(f"{router.prefix}/exec_sql 调用错误", "WebUi", e=e)
|
||||
await SqlLog.add(ip or "0.0.0.0", sql.sql, str(e), False)
|
||||
return Result.warning_(f"sql执行错误: {e}")
|
||||
|
||||
@@ -176,16 +115,20 @@ async def _(sql: SqlText, request: Request) -> Result[list[dict]]:
|
||||
description="sql日志列表",
|
||||
)
|
||||
async def _(query: QueryModel) -> Result[BaseResultModel]:
|
||||
total = await SqlLog.all().count()
|
||||
if total % query.size:
|
||||
total += 1
|
||||
data = (
|
||||
await SqlLog.all()
|
||||
.order_by("-id")
|
||||
.offset((query.index - 1) * query.size)
|
||||
.limit(query.size)
|
||||
)
|
||||
return Result.ok(BaseResultModel(total=total, data=data))
|
||||
try:
|
||||
total = await SqlLog.all().count()
|
||||
if total % query.size:
|
||||
total += 1
|
||||
data = (
|
||||
await SqlLog.all()
|
||||
.order_by("-id")
|
||||
.offset((query.index - 1) * query.size)
|
||||
.limit(query.size)
|
||||
)
|
||||
return Result.ok(BaseResultModel(total=total, data=data))
|
||||
except Exception as e:
|
||||
logger.error(f"{router.prefix}/get_sql_log 调用错误", "WebUi", e=e)
|
||||
return Result.fail(f"发生了一点错误捏 {type(e)}: {e}")
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -197,5 +140,5 @@ async def _(query: QueryModel) -> Result[BaseResultModel]:
|
||||
)
|
||||
async def _(plugin_name: str | None = None) -> Result[dict]:
|
||||
if plugin_name:
|
||||
return Result.ok(SQL_DICT.get(plugin_name))
|
||||
return Result.ok(str(SQL_DICT))
|
||||
return Result.ok(ApiDataSource.SQL_DICT.get(plugin_name))
|
||||
return Result.ok(str(ApiDataSource.SQL_DICT))
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
from tortoise import Tortoise
|
||||
|
||||
from zhenxun.configs.config import BotConfig
|
||||
|
||||
from .models.model import Column
|
||||
|
||||
SELECT_TABLE_MYSQL_SQL = """
|
||||
SELECT table_name AS name, table_comment AS `desc`
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = DATABASE();
|
||||
"""
|
||||
|
||||
SELECT_TABLE_SQLITE_SQL = """
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
"""
|
||||
|
||||
SELECT_TABLE_PSQL_SQL = """
|
||||
select a.tablename as name,d.description as desc from pg_tables a
|
||||
left join pg_class c on relname=tablename
|
||||
left join pg_description d on oid=objoid and objsubid=0 where a.schemaname='public'
|
||||
"""
|
||||
|
||||
SELECT_TABLE_COLUMN_PSQL_SQL = """
|
||||
SELECT column_name, data_type, character_maximum_length as max_length, is_nullable
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = '{}';
|
||||
"""
|
||||
|
||||
SELECT_TABLE_COLUMN_MYSQL_SQL = """
|
||||
SHOW COLUMNS FROM {};
|
||||
"""
|
||||
|
||||
SELECT_TABLE_COLUMN_SQLITE_SQL = """
|
||||
PRAGMA table_info({});
|
||||
"""
|
||||
|
||||
type2sql = {
|
||||
"mysql": SELECT_TABLE_MYSQL_SQL,
|
||||
"sqlite": SELECT_TABLE_SQLITE_SQL,
|
||||
"postgres": SELECT_TABLE_PSQL_SQL,
|
||||
}
|
||||
|
||||
type2sql_column = {
|
||||
"mysql": SELECT_TABLE_COLUMN_MYSQL_SQL,
|
||||
"sqlite": SELECT_TABLE_COLUMN_SQLITE_SQL,
|
||||
"postgres": SELECT_TABLE_COLUMN_PSQL_SQL,
|
||||
}
|
||||
|
||||
|
||||
class ApiDataSource:
|
||||
SQL_DICT = {} # noqa: RUF012
|
||||
|
||||
@classmethod
|
||||
async def get_table_column(cls, table_name: str) -> list[Column]:
|
||||
"""获取表字段信息
|
||||
|
||||
参数:
|
||||
table_name: 表名
|
||||
|
||||
返回:
|
||||
list[Column]: 字段数据
|
||||
"""
|
||||
db = Tortoise.get_connection("default")
|
||||
sql_type = BotConfig.get_sql_type()
|
||||
sql = type2sql_column[sql_type]
|
||||
query = await db.execute_query_dict(sql.format(table_name))
|
||||
result_list = []
|
||||
if sql_type == "sqlite":
|
||||
result_list.extend(
|
||||
Column(
|
||||
column_name=result["name"],
|
||||
data_type=result["type"],
|
||||
max_length=-1,
|
||||
is_nullable="YES" if result["notnull"] == 1 else "NO",
|
||||
)
|
||||
for result in query
|
||||
)
|
||||
elif sql_type == "mysql":
|
||||
result_list.extend(
|
||||
Column(
|
||||
column_name=result["Field"],
|
||||
data_type=result["Type"],
|
||||
max_length=-1,
|
||||
is_nullable=result["Null"],
|
||||
)
|
||||
for result in query
|
||||
)
|
||||
else:
|
||||
result_list.extend(Column(**result) for result in query)
|
||||
return result_list
|
||||
Reference in New Issue
Block a user