From 1516c1a941956ed5cdd7e58c82994be97f99ecba Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 5 Dec 2025 10:00:25 +0800 Subject: [PATCH 01/49] =?UTF-8?q?refactor&perf:=20=E5=A2=9E=E5=BC=BAruff?= =?UTF-8?q?=E8=A7=84=E5=88=99=EF=BC=8C=E5=AE=8C=E5=96=84=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/alembic/env.py | 17 +- ruoyi-fastapi-backend/app.py | 2 +- ruoyi-fastapi-backend/config/constant.py | 2 + ruoyi-fastapi-backend/config/database.py | 8 +- ruoyi-fastapi-backend/config/enums.py | 5 +- ruoyi-fastapi-backend/config/env.py | 32 +- ruoyi-fastapi-backend/config/get_db.py | 10 +- ruoyi-fastapi-backend/config/get_redis.py | 13 +- ruoyi-fastapi-backend/config/get_scheduler.py | 87 ++--- ruoyi-fastapi-backend/exceptions/exception.py | 15 +- ruoyi-fastapi-backend/exceptions/handle.py | 25 +- .../middlewares/cors_middleware.py | 2 +- .../middlewares/gzip_middleware.py | 2 +- ruoyi-fastapi-backend/middlewares/handle.py | 3 +- .../middlewares/trace_middleware/__init__.py | 3 +- .../middlewares/trace_middleware/ctx.py | 11 +- .../middlewares/trace_middleware/middle.py | 15 +- .../middlewares/trace_middleware/span.py | 22 +- .../module_admin/annotation/log_annotation.py | 345 +++++++++++++----- .../annotation/pydantic_annotation.py | 30 +- .../module_admin/aspect/data_scope.py | 12 +- .../module_admin/aspect/interface_auth.py | 36 +- .../controller/cache_controller.py | 47 ++- .../controller/captcha_controller.py | 24 +- .../controller/common_controller.py | 23 +- .../controller/config_controller.py | 67 ++-- .../controller/dept_controller.py | 75 ++-- .../controller/dict_controller.py | 125 ++++--- .../module_admin/controller/job_controller.py | 103 +++--- .../module_admin/controller/log_controller.py | 72 ++-- .../controller/login_controller.py | 56 +-- .../controller/menu_controller.py | 71 ++-- .../controller/notice_controller.py | 48 ++- .../controller/online_controller.py | 23 +- .../{post_controler.py => post_controller.py} | 60 +-- .../controller/role_controller.py | 150 ++++---- .../controller/server_controller.py | 14 +- .../controller/user_controller.py | 202 +++++----- .../module_admin/dao/config_dao.py | 23 +- .../module_admin/dao/dept_dao.py | 39 +- .../module_admin/dao/dict_dao.py | 50 ++- .../module_admin/dao/job_dao.py | 26 +- .../module_admin/dao/job_log_dao.py | 19 +- .../module_admin/dao/log_dao.py | 33 +- .../module_admin/dao/login_dao.py | 7 +- .../module_admin/dao/menu_dao.py | 24 +- .../module_admin/dao/notice_dao.py | 23 +- .../module_admin/dao/post_dao.py | 27 +- .../module_admin/dao/role_dao.py | 44 ++- .../module_admin/dao/user_dao.py | 82 +++-- .../module_admin/entity/do/config_do.py | 2 + .../module_admin/entity/do/dept_do.py | 4 +- .../module_admin/entity/do/dict_do.py | 4 +- .../module_admin/entity/do/job_do.py | 4 +- .../module_admin/entity/do/log_do.py | 8 +- .../module_admin/entity/do/menu_do.py | 4 +- .../module_admin/entity/do/notice_do.py | 2 + .../module_admin/entity/do/post_do.py | 4 +- .../module_admin/entity/do/role_do.py | 4 +- .../module_admin/entity/do/user_do.py | 4 +- .../module_admin/entity/vo/cache_vo.py | 5 +- .../module_admin/entity/vo/common_vo.py | 3 +- .../module_admin/entity/vo/config_vo.py | 13 +- .../module_admin/entity/vo/dept_vo.py | 15 +- .../module_admin/entity/vo/dict_vo.py | 22 +- .../module_admin/entity/vo/job_vo.py | 12 +- .../module_admin/entity/vo/log_vo.py | 6 +- .../module_admin/entity/vo/login_vo.py | 11 +- .../module_admin/entity/vo/menu_vo.py | 19 +- .../module_admin/entity/vo/notice_vo.py | 9 +- .../module_admin/entity/vo/online_vo.py | 5 +- .../module_admin/entity/vo/post_vo.py | 13 +- .../module_admin/entity/vo/role_vo.py | 27 +- .../module_admin/entity/vo/server_vo.py | 5 +- .../module_admin/entity/vo/user_vo.py | 46 ++- .../module_admin/service/cache_service.py | 38 +- .../module_admin/service/captcha_service.py | 3 +- .../module_admin/service/common_service.py | 75 ++-- .../module_admin/service/config_service.py | 94 ++--- .../module_admin/service/dept_service.py | 70 ++-- .../module_admin/service/dict_service.py | 182 ++++----- .../module_admin/service/job_log_service.py | 33 +- .../module_admin/service/job_service.py | 98 ++--- .../module_admin/service/log_service.py | 38 +- .../module_admin/service/login_service.py | 123 ++++--- .../module_admin/service/menu_service.py | 85 ++--- .../module_admin/service/notice_service.py | 51 ++- .../module_admin/service/online_service.py | 30 +- .../module_admin/service/post_service.py | 60 ++- .../module_admin/service/role_service.py | 84 +++-- .../module_admin/service/server_service.py | 6 +- .../module_admin/service/user_service.py | 187 ++++++---- .../controller/gen_controller.py | 104 ++++-- .../module_generator/dao/gen_dao.py | 152 ++++---- .../module_generator/entity/do/gen_do.py | 4 +- .../module_generator/entity/vo/gen_vo.py | 63 ++-- .../module_generator/service/gen_service.py | 104 +++--- .../templates/python/controller.py.jinja2 | 57 +-- .../templates/python/dao.py.jinja2 | 29 +- .../templates/python/do.py.jinja2 | 1 + .../templates/python/service.py.jinja2 | 32 +- .../templates/python/vo.py.jinja2 | 25 +- .../module_task/scheduler_test.py | 4 +- ruoyi-fastapi-backend/requirements-pg.txt | 4 +- ruoyi-fastapi-backend/requirements.txt | 4 +- ruoyi-fastapi-backend/ruff.toml | 64 ++++ ruoyi-fastapi-backend/server.py | 73 ++-- .../sub_applications/handle.py | 3 +- .../sub_applications/staticfiles.py | 3 +- ruoyi-fastapi-backend/utils/common_util.py | 178 +++++++-- ruoyi-fastapi-backend/utils/cron_util.py | 74 ++-- ruoyi-fastapi-backend/utils/excel_util.py | 8 +- ruoyi-fastapi-backend/utils/gen_util.py | 15 +- ruoyi-fastapi-backend/utils/import_util.py | 14 +- ruoyi-fastapi-backend/utils/log_util.py | 12 +- ruoyi-fastapi-backend/utils/message_util.py | 2 +- ruoyi-fastapi-backend/utils/page_util.py | 24 +- ruoyi-fastapi-backend/utils/pwd_util.py | 2 +- ruoyi-fastapi-backend/utils/response_util.py | 15 +- ruoyi-fastapi-backend/utils/string_util.py | 39 +- ruoyi-fastapi-backend/utils/template_util.py | 62 ++-- .../utils/time_format_util.py | 41 ++- ruoyi-fastapi-backend/utils/upload_util.py | 39 +- 123 files changed, 2871 insertions(+), 2142 deletions(-) rename ruoyi-fastapi-backend/module_admin/controller/{post_controler.py => post_controller.py} (67%) diff --git a/ruoyi-fastapi-backend/alembic/env.py b/ruoyi-fastapi-backend/alembic/env.py index 98828e6..88469e0 100644 --- a/ruoyi-fastapi-backend/alembic/env.py +++ b/ruoyi-fastapi-backend/alembic/env.py @@ -1,13 +1,18 @@ import asyncio import os -from alembic import context +from collections.abc import Iterable from logging.config import fileConfig +from typing import Optional, Union + +from alembic import context +from alembic.migration import MigrationContext +from alembic.operations.ops import MigrationScript from sqlalchemy import pool from sqlalchemy.engine import Connection from sqlalchemy.ext.asyncio import async_engine_from_config -from config.database import Base, ASYNC_SQLALCHEMY_DATABASE_URL -from utils.import_util import ImportUtil +from config.database import ASYNC_SQLALCHEMY_DATABASE_URL, Base +from utils.import_util import ImportUtil # 判断vesrions目录是否存在,如果不存在则创建 alembic_veresions_path = 'alembic/versions' @@ -60,7 +65,11 @@ def run_migrations_offline() -> None: def do_run_migrations(connection: Connection) -> None: - def process_revision_directives(context, revision, directives): + def process_revision_directives( + context: MigrationContext, + revision: Union[str, Iterable[Optional[str]], Iterable[str]], + directives: list[MigrationScript], + ) -> None: script = directives[0] # 检查所有操作集是否为空 diff --git a/ruoyi-fastapi-backend/app.py b/ruoyi-fastapi-backend/app.py index 1ee7695..9c7e7d5 100644 --- a/ruoyi-fastapi-backend/app.py +++ b/ruoyi-fastapi-backend/app.py @@ -1,6 +1,6 @@ import uvicorn -from server import app, AppConfig # noqa: F401 +from server import AppConfig, app # noqa: F401 if __name__ == '__main__': uvicorn.run( diff --git a/ruoyi-fastapi-backend/config/constant.py b/ruoyi-fastapi-backend/config/constant.py index eb77464..da70e15 100644 --- a/ruoyi-fastapi-backend/config/constant.py +++ b/ruoyi-fastapi-backend/config/constant.py @@ -5,6 +5,7 @@ class CommonConstant: """ 常用常量 + PASSWORD_ERROR_COUNT: 密码错误次数 WWW: www主域 HTTP: http请求 HTTPS: https请求 @@ -19,6 +20,7 @@ class CommonConstant: NOT_UNIQUE: 校验是否唯一的返回标识(否) """ + PASSWORD_ERROR_COUNT = 5 WWW = 'www.' HTTP = 'http://' HTTPS = 'https://' diff --git a/ruoyi-fastapi-backend/config/database.py b/ruoyi-fastapi-backend/config/database.py index 006b6a5..72e0ce4 100644 --- a/ruoyi-fastapi-backend/config/database.py +++ b/ruoyi-fastapi-backend/config/database.py @@ -1,8 +1,8 @@ -from sqlalchemy.ext.asyncio import create_async_engine -from sqlalchemy.ext.asyncio import async_sessionmaker -from sqlalchemy.ext.asyncio import AsyncAttrs -from sqlalchemy.orm import DeclarativeBase from urllib.parse import quote_plus + +from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine +from sqlalchemy.orm import DeclarativeBase + from config.env import DataBaseConfig ASYNC_SQLALCHEMY_DATABASE_URL = ( diff --git a/ruoyi-fastapi-backend/config/enums.py b/ruoyi-fastapi-backend/config/enums.py index 0df6238..b6c3fda 100644 --- a/ruoyi-fastapi-backend/config/enums.py +++ b/ruoyi-fastapi-backend/config/enums.py @@ -1,4 +1,5 @@ from enum import Enum +from typing import Union class BusinessType(Enum): @@ -35,11 +36,11 @@ class RedisInitKeyConfig(Enum): """ @property - def key(self): + def key(self) -> Union[str, None]: return self.value.get('key') @property - def remark(self): + def remark(self) -> Union[str, None]: return self.value.get('remark') ACCESS_TOKEN = {'key': 'access_token', 'remark': '登录令牌信息'} diff --git a/ruoyi-fastapi-backend/config/env.py b/ruoyi-fastapi-backend/config/env.py index 3a2b3af..153b7a1 100644 --- a/ruoyi-fastapi-backend/config/env.py +++ b/ruoyi-fastapi-backend/config/env.py @@ -2,11 +2,11 @@ import argparse import configparser import os import sys +from typing import Literal + from dotenv import load_dotenv -from functools import lru_cache from pydantic import computed_field from pydantic_settings import BaseSettings -from typing import Literal class AppSettings(BaseSettings): @@ -86,7 +86,7 @@ class GenSettings: GEN_PATH = 'vf_admin/gen_path' - def __init__(self): + def __init__(self) -> None: if not os.path.exists(self.GEN_PATH): os.makedirs(self.GEN_PATH) @@ -130,7 +130,7 @@ class UploadSettings: ] DOWNLOAD_PATH = 'vf_admin/download_path' - def __init__(self): + def __init__(self) -> None: if not os.path.exists(self.UPLOAD_PATH): os.makedirs(self.UPLOAD_PATH) if not os.path.exists(self.DOWNLOAD_PATH): @@ -151,59 +151,53 @@ class GetConfig: 获取配置 """ - def __init__(self): + def __init__(self) -> None: self.parse_cli_args() - @lru_cache() - def get_app_config(self): + def get_app_config(self) -> AppSettings: """ 获取应用配置 """ # 实例化应用配置模型 return AppSettings() - @lru_cache() - def get_jwt_config(self): + def get_jwt_config(self) -> JwtSettings: """ 获取Jwt配置 """ # 实例化Jwt配置模型 return JwtSettings() - @lru_cache() - def get_database_config(self): + def get_database_config(self) -> DataBaseSettings: """ 获取数据库配置 """ # 实例化数据库配置模型 return DataBaseSettings() - @lru_cache() - def get_redis_config(self): + def get_redis_config(self) -> RedisSettings: """ 获取Redis配置 """ # 实例化Redis配置模型 return RedisSettings() - @lru_cache() - def get_gen_config(self): + def get_gen_config(self) -> GenSettings: """ 获取代码生成配置 """ # 实例化代码生成配置 return GenSettings() - @lru_cache() - def get_upload_config(self): + def get_upload_config(self) -> UploadSettings: """ - 获取数据库配置 + 获取上传配置 """ # 实例上传配置 return UploadSettings() @staticmethod - def parse_cli_args(): + def parse_cli_args() -> None: """ 解析命令行参数 """ diff --git a/ruoyi-fastapi-backend/config/get_db.py b/ruoyi-fastapi-backend/config/get_db.py index e5930c7..16df0ab 100644 --- a/ruoyi-fastapi-backend/config/get_db.py +++ b/ruoyi-fastapi-backend/config/get_db.py @@ -1,8 +1,12 @@ -from config.database import async_engine, AsyncSessionLocal, Base +from collections.abc import AsyncGenerator + +from sqlalchemy.ext.asyncio import AsyncSession + +from config.database import AsyncSessionLocal, Base, async_engine from utils.log_util import logger -async def get_db(): +async def get_db() -> AsyncGenerator[AsyncSession, None]: """ 每一个请求处理完毕后会关闭当前连接,不同的请求使用不同的连接 @@ -12,7 +16,7 @@ async def get_db(): yield current_db -async def init_create_table(): +async def init_create_table() -> None: """ 应用启动时初始化数据库连接 diff --git a/ruoyi-fastapi-backend/config/get_redis.py b/ruoyi-fastapi-backend/config/get_redis.py index ee4b6bd..e477784 100644 --- a/ruoyi-fastapi-backend/config/get_redis.py +++ b/ruoyi-fastapi-backend/config/get_redis.py @@ -1,5 +1,8 @@ +from fastapi import FastAPI from redis import asyncio as aioredis -from redis.exceptions import AuthenticationError, TimeoutError, RedisError +from redis.exceptions import AuthenticationError, RedisError +from redis.exceptions import TimeoutError as RedisTimeoutError + from config.database import AsyncSessionLocal from config.env import RedisConfig from module_admin.service.config_service import ConfigService @@ -37,14 +40,14 @@ class RedisUtil: logger.error('❌️ redis连接失败') except AuthenticationError as e: logger.error(f'❌️ redis用户名或密码错误,详细错误信息:{e}') - except TimeoutError as e: + except RedisTimeoutError as e: logger.error(f'❌️ redis连接超时,详细错误信息:{e}') except RedisError as e: logger.error(f'❌️ redis连接错误,详细错误信息:{e}') return redis @classmethod - async def close_redis_pool(cls, app): + async def close_redis_pool(cls, app: FastAPI) -> None: """ 应用关闭时关闭redis连接 @@ -55,7 +58,7 @@ class RedisUtil: logger.info('✅️ 关闭redis连接成功') @classmethod - async def init_sys_dict(cls, redis): + async def init_sys_dict(cls, redis: FastAPI) -> None: """ 应用启动时缓存字典表 @@ -66,7 +69,7 @@ class RedisUtil: await DictDataService.init_cache_sys_dict_services(session, redis) @classmethod - async def init_sys_config(cls, redis): + async def init_sys_config(cls, redis: aioredis.Redis) -> None: """ 应用启动时缓存参数配置表 diff --git a/ruoyi-fastapi-backend/config/get_scheduler.py b/ruoyi-fastapi-backend/config/get_scheduler.py index fadcf02..204adb4 100644 --- a/ruoyi-fastapi-backend/config/get_scheduler.py +++ b/ruoyi-fastapi-backend/config/get_scheduler.py @@ -1,7 +1,12 @@ import json -from apscheduler.events import EVENT_ALL +from asyncio import iscoroutinefunction +from datetime import datetime, timedelta +from typing import Optional, Union + +from apscheduler.events import EVENT_ALL, SchedulerEvent from apscheduler.executors.asyncio import AsyncIOExecutor from apscheduler.executors.pool import ProcessPoolExecutor +from apscheduler.job import Job from apscheduler.jobstores.memory import MemoryJobStore from apscheduler.jobstores.redis import RedisJobStore from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore @@ -9,27 +14,29 @@ from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.combining import OrTrigger from apscheduler.triggers.cron import CronTrigger from apscheduler.triggers.date import DateTrigger -from asyncio import iscoroutinefunction -from datetime import datetime, timedelta from sqlalchemy.engine import create_engine from sqlalchemy.orm import sessionmaker -from typing import Union + +import module_task # noqa: F401 from config.database import AsyncSessionLocal, quote_plus from config.env import DataBaseConfig, RedisConfig from module_admin.dao.job_dao import JobDao from module_admin.entity.vo.job_vo import JobLogModel, JobModel from module_admin.service.job_log_service import JobLogService from utils.log_util import logger -import module_task # noqa: F401 # 重写Cron定时 class MyCronTrigger(CronTrigger): + CRON_EXPRESSION_LENGTH_MIN = 6 + CRON_EXPRESSION_LENGTH_MAX = 7 + WEEKDAY_COUNT = 5 + @classmethod - def from_crontab(cls, expr: str, timezone=None): + def from_crontab(cls, expr: str, timezone: Optional[str] = None) -> 'MyCronTrigger': values = expr.split() - if len(values) != 6 and len(values) != 7: - raise ValueError('Wrong number of fields; got {}, expected 6 or 7'.format(len(values))) + if len(values) != cls.CRON_EXPRESSION_LENGTH_MIN and len(values) != cls.CRON_EXPRESSION_LENGTH_MAX: + raise ValueError(f'Wrong number of fields; got {len(values)}, expected 6 or 7') second = values[0] minute = values[1] @@ -37,7 +44,7 @@ class MyCronTrigger(CronTrigger): if '?' in values[3]: day = None elif 'L' in values[5]: - day = f"last {values[5].replace('L', '')}" + day = f'last {values[5].replace("L", "")}' elif 'W' in values[3]: day = cls.__find_recent_workday(int(values[3].split('W')[0])) else: @@ -49,11 +56,8 @@ class MyCronTrigger(CronTrigger): week = int(values[5].split('#')[1]) else: week = values[5] - if '#' in values[5]: - day_of_week = int(values[5].split('#')[0]) - 1 - else: - day_of_week = None - year = values[6] if len(values) == 7 else None + day_of_week = int(values[5].split('#')[0]) - 1 if '#' in values[5] else None + year = values[6] if len(values) == cls.CRON_EXPRESSION_LENGTH_MAX else None return cls( second=second, minute=minute, @@ -67,19 +71,17 @@ class MyCronTrigger(CronTrigger): ) @classmethod - def __find_recent_workday(cls, day: int): + def __find_recent_workday(cls, day: int) -> int: now = datetime.now() date = datetime(now.year, now.month, day) - if date.weekday() < 5: + if date.weekday() < cls.WEEKDAY_COUNT: return date.day - else: - diff = 1 - while True: - previous_day = date - timedelta(days=diff) - if previous_day.weekday() < 5: - return previous_day.day - else: - diff += 1 + diff = 1 + while True: + previous_day = date - timedelta(days=diff) + if previous_day.weekday() < cls.WEEKDAY_COUNT: + return previous_day.day + diff += 1 SQLALCHEMY_DATABASE_URL = ( @@ -100,18 +102,17 @@ engine = create_engine( pool_timeout=DataBaseConfig.db_pool_timeout, ) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) +redis_config = { + 'host': RedisConfig.redis_host, + 'port': RedisConfig.redis_port, + 'username': RedisConfig.redis_username, + 'password': RedisConfig.redis_password, + 'db': RedisConfig.redis_database, +} job_stores = { 'default': MemoryJobStore(), 'sqlalchemy': SQLAlchemyJobStore(url=SQLALCHEMY_DATABASE_URL, engine=engine), - 'redis': RedisJobStore( - **dict( - host=RedisConfig.redis_host, - port=RedisConfig.redis_port, - username=RedisConfig.redis_username, - password=RedisConfig.redis_password, - db=RedisConfig.redis_database, - ) - ), + 'redis': RedisJobStore(**redis_config), } executors = {'default': AsyncIOExecutor(), 'processpool': ProcessPoolExecutor(5)} job_defaults = {'coalesce': False, 'max_instance': 1} @@ -125,7 +126,7 @@ class SchedulerUtil: """ @classmethod - async def init_system_scheduler(cls): + async def init_system_scheduler(cls) -> None: """ 应用启动时初始化定时任务 @@ -142,7 +143,7 @@ class SchedulerUtil: logger.info('✅️ 系统初始定时任务加载成功') @classmethod - async def close_system_scheduler(cls): + async def close_system_scheduler(cls) -> None: """ 应用关闭时关闭定时任务 @@ -152,7 +153,7 @@ class SchedulerUtil: logger.info('✅️ 关闭定时任务成功') @classmethod - def get_scheduler_job(cls, job_id: Union[str, int]): + def get_scheduler_job(cls, job_id: Union[str, int]) -> Job: """ 根据任务id获取任务对象 @@ -164,7 +165,7 @@ class SchedulerUtil: return query_job @classmethod - def add_scheduler_job(cls, job_info: JobModel): + def add_scheduler_job(cls, job_info: JobModel) -> None: """ 根据输入的任务对象信息添加任务 @@ -183,14 +184,14 @@ class SchedulerUtil: id=str(job_info.job_id), name=job_info.job_name, misfire_grace_time=1000000000000 if job_info.misfire_policy == '3' else None, - coalesce=True if job_info.misfire_policy == '2' else False, + coalesce=job_info.misfire_policy == '2', max_instances=3 if job_info.concurrent == '0' else 1, jobstore=job_info.job_group, executor=job_executor, ) @classmethod - def execute_scheduler_job_once(cls, job_info: JobModel): + def execute_scheduler_job_once(cls, job_info: JobModel) -> None: """ 根据输入的任务对象执行一次任务 @@ -212,14 +213,14 @@ class SchedulerUtil: id=str(job_info.job_id), name=job_info.job_name, misfire_grace_time=1000000000000 if job_info.misfire_policy == '3' else None, - coalesce=True if job_info.misfire_policy == '2' else False, + coalesce=job_info.misfire_policy == '2', max_instances=3 if job_info.concurrent == '0' else 1, jobstore=job_info.job_group, executor=job_executor, ) @classmethod - def remove_scheduler_job(cls, job_id: Union[str, int]): + def remove_scheduler_job(cls, job_id: Union[str, int]) -> None: """ 根据任务id移除任务 @@ -231,7 +232,7 @@ class SchedulerUtil: scheduler.remove_job(job_id=str(job_id)) @classmethod - def scheduler_event_listener(cls, event): + def scheduler_event_listener(cls, event: SchedulerEvent) -> None: # 获取事件类型和任务ID event_type = event.__class__.__name__ # 获取任务执行异常信息 @@ -260,7 +261,7 @@ class SchedulerUtil: # 获取任务触发器 job_trigger = str(query_job_info.get('trigger')) # 构造日志消息 - job_message = f"事件类型: {event_type}, 任务ID: {job_id}, 任务名称: {job_name}, 执行于{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" + job_message = f'事件类型: {event_type}, 任务ID: {job_id}, 任务名称: {job_name}, 执行于{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}' job_log = JobLogModel( jobName=job_name, jobGroup=job_group, diff --git a/ruoyi-fastapi-backend/exceptions/exception.py b/ruoyi-fastapi-backend/exceptions/exception.py index b86f50d..effaa9e 100644 --- a/ruoyi-fastapi-backend/exceptions/exception.py +++ b/ruoyi-fastapi-backend/exceptions/exception.py @@ -1,9 +1,12 @@ +from typing import Optional + + class LoginException(Exception): """ 自定义登录异常LoginException """ - def __init__(self, data: str = None, message: str = None): + def __init__(self, data: Optional[str] = None, message: Optional[str] = None) -> None: self.data = data self.message = message @@ -13,7 +16,7 @@ class AuthException(Exception): 自定义令牌异常AuthException """ - def __init__(self, data: str = None, message: str = None): + def __init__(self, data: Optional[str] = None, message: Optional[str] = None) -> None: self.data = data self.message = message @@ -23,7 +26,7 @@ class PermissionException(Exception): 自定义权限异常PermissionException """ - def __init__(self, data: str = None, message: str = None): + def __init__(self, data: Optional[str] = None, message: Optional[str] = None) -> None: self.data = data self.message = message @@ -33,7 +36,7 @@ class ServiceException(Exception): 自定义服务异常ServiceException """ - def __init__(self, data: str = None, message: str = None): + def __init__(self, data: Optional[str] = None, message: Optional[str] = None) -> None: self.data = data self.message = message @@ -43,7 +46,7 @@ class ServiceWarning(Exception): 自定义服务警告ServiceWarning """ - def __init__(self, data: str = None, message: str = None): + def __init__(self, data: Optional[str] = None, message: Optional[str] = None) -> None: self.data = data self.message = message @@ -53,6 +56,6 @@ class ModelValidatorException(Exception): 自定义模型校验异常ModelValidatorException """ - def __init__(self, data: str = None, message: str = None): + def __init__(self, data: Optional[str] = None, message: Optional[str] = None) -> None: self.data = data self.message = message diff --git a/ruoyi-fastapi-backend/exceptions/handle.py b/ruoyi-fastapi-backend/exceptions/handle.py index dec516a..3e8e590 100644 --- a/ruoyi-fastapi-backend/exceptions/handle.py +++ b/ruoyi-fastapi-backend/exceptions/handle.py @@ -1,6 +1,7 @@ -from fastapi import FastAPI, Request +from fastapi import FastAPI, Request, Response from fastapi.exceptions import HTTPException from pydantic_validation_decorator import FieldValidationError + from exceptions.exception import ( AuthException, LoginException, @@ -10,62 +11,62 @@ from exceptions.exception import ( ServiceWarning, ) from utils.log_util import logger -from utils.response_util import jsonable_encoder, JSONResponse, ResponseUtil +from utils.response_util import JSONResponse, ResponseUtil, jsonable_encoder -def handle_exception(app: FastAPI): +def handle_exception(app: FastAPI) -> None: """ 全局异常处理 """ # 自定义token检验异常 @app.exception_handler(AuthException) - async def auth_exception_handler(request: Request, exc: AuthException): + async def auth_exception_handler(request: Request, exc: AuthException) -> Response: return ResponseUtil.unauthorized(data=exc.data, msg=exc.message) # 自定义登录检验异常 @app.exception_handler(LoginException) - async def login_exception_handler(request: Request, exc: LoginException): + async def login_exception_handler(request: Request, exc: LoginException) -> Response: return ResponseUtil.failure(data=exc.data, msg=exc.message) # 自定义模型检验异常 @app.exception_handler(ModelValidatorException) - async def model_validator_exception_handler(request: Request, exc: ModelValidatorException): + async def model_validator_exception_handler(request: Request, exc: ModelValidatorException) -> Response: logger.warning(exc.message) return ResponseUtil.failure(data=exc.data, msg=exc.message) # 自定义字段检验异常 @app.exception_handler(FieldValidationError) - async def field_validation_error_handler(request: Request, exc: FieldValidationError): + async def field_validation_error_handler(request: Request, exc: FieldValidationError) -> Response: logger.warning(exc.message) return ResponseUtil.failure(msg=exc.message) # 自定义权限检验异常 @app.exception_handler(PermissionException) - async def permission_exception_handler(request: Request, exc: PermissionException): + async def permission_exception_handler(request: Request, exc: PermissionException) -> Response: return ResponseUtil.forbidden(data=exc.data, msg=exc.message) # 自定义服务异常 @app.exception_handler(ServiceException) - async def service_exception_handler(request: Request, exc: ServiceException): + async def service_exception_handler(request: Request, exc: ServiceException) -> Response: logger.error(exc.message) return ResponseUtil.error(data=exc.data, msg=exc.message) # 自定义服务警告 @app.exception_handler(ServiceWarning) - async def service_warning_handler(request: Request, exc: ServiceWarning): + async def service_warning_handler(request: Request, exc: ServiceWarning) -> Response: logger.warning(exc.message) return ResponseUtil.failure(data=exc.data, msg=exc.message) # 处理其他http请求异常 @app.exception_handler(HTTPException) - async def http_exception_handler(request: Request, exc: HTTPException): + async def http_exception_handler(request: Request, exc: HTTPException) -> Response: return JSONResponse( content=jsonable_encoder({'code': exc.status_code, 'msg': exc.detail}), status_code=exc.status_code ) # 处理其他异常 @app.exception_handler(Exception) - async def exception_handler(request: Request, exc: Exception): + async def exception_handler(request: Request, exc: Exception) -> Response: logger.exception(exc) return ResponseUtil.error(msg=str(exc)) diff --git a/ruoyi-fastapi-backend/middlewares/cors_middleware.py b/ruoyi-fastapi-backend/middlewares/cors_middleware.py index 55508e7..e82ca9c 100644 --- a/ruoyi-fastapi-backend/middlewares/cors_middleware.py +++ b/ruoyi-fastapi-backend/middlewares/cors_middleware.py @@ -2,7 +2,7 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -def add_cors_middleware(app: FastAPI): +def add_cors_middleware(app: FastAPI) -> None: """ 添加跨域中间件 diff --git a/ruoyi-fastapi-backend/middlewares/gzip_middleware.py b/ruoyi-fastapi-backend/middlewares/gzip_middleware.py index eb371ce..867b786 100644 --- a/ruoyi-fastapi-backend/middlewares/gzip_middleware.py +++ b/ruoyi-fastapi-backend/middlewares/gzip_middleware.py @@ -2,7 +2,7 @@ from fastapi import FastAPI from starlette.middleware.gzip import GZipMiddleware -def add_gzip_middleware(app: FastAPI): +def add_gzip_middleware(app: FastAPI) -> None: """ 添加gzip压缩中间件 diff --git a/ruoyi-fastapi-backend/middlewares/handle.py b/ruoyi-fastapi-backend/middlewares/handle.py index abb2d0d..bc2aca9 100644 --- a/ruoyi-fastapi-backend/middlewares/handle.py +++ b/ruoyi-fastapi-backend/middlewares/handle.py @@ -1,10 +1,11 @@ from fastapi import FastAPI + from middlewares.cors_middleware import add_cors_middleware from middlewares.gzip_middleware import add_gzip_middleware from middlewares.trace_middleware import add_trace_middleware -def handle_middleware(app: FastAPI): +def handle_middleware(app: FastAPI) -> None: """ 全局中间件处理 """ diff --git a/ruoyi-fastapi-backend/middlewares/trace_middleware/__init__.py b/ruoyi-fastapi-backend/middlewares/trace_middleware/__init__.py index 76f8d85..c2ea302 100644 --- a/ruoyi-fastapi-backend/middlewares/trace_middleware/__init__.py +++ b/ruoyi-fastapi-backend/middlewares/trace_middleware/__init__.py @@ -1,4 +1,5 @@ from fastapi import FastAPI + from .ctx import TraceCtx from .middle import TraceASGIMiddleware @@ -7,7 +8,7 @@ __all__ = ('TraceASGIMiddleware', 'TraceCtx') __version__ = '0.1.0' -def add_trace_middleware(app: FastAPI): +def add_trace_middleware(app: FastAPI) -> None: """ 添加trace中间件 diff --git a/ruoyi-fastapi-backend/middlewares/trace_middleware/ctx.py b/ruoyi-fastapi-backend/middlewares/trace_middleware/ctx.py index 558a5c9..4f98008 100644 --- a/ruoyi-fastapi-backend/middlewares/trace_middleware/ctx.py +++ b/ruoyi-fastapi-backend/middlewares/trace_middleware/ctx.py @@ -1,10 +1,3 @@ -# -*- coding: utf-8 -*- -""" -@author: peng -@file: ctx.py -@time: 2025/1/17 16:57 -""" - import contextvars from uuid import uuid4 @@ -13,11 +6,11 @@ CTX_REQUEST_ID: contextvars.ContextVar[str] = contextvars.ContextVar('request-id class TraceCtx: @staticmethod - def set_id(): + def set_id() -> str: _id = uuid4().hex CTX_REQUEST_ID.set(_id) return _id @staticmethod - def get_id(): + def get_id() -> str: return CTX_REQUEST_ID.get() diff --git a/ruoyi-fastapi-backend/middlewares/trace_middleware/middle.py b/ruoyi-fastapi-backend/middlewares/trace_middleware/middle.py index a071692..42cd78c 100644 --- a/ruoyi-fastapi-backend/middlewares/trace_middleware/middle.py +++ b/ruoyi-fastapi-backend/middlewares/trace_middleware/middle.py @@ -1,13 +1,8 @@ -# -*- coding: utf-8 -*- -""" -@author: peng -@file: middle.py -@time: 2025/1/17 16:57 -""" - from functools import wraps + from starlette.types import ASGIApp, Message, Receive, Scope, Send -from .span import get_current_span, Span + +from .span import Span, get_current_span class TraceASGIMiddleware: @@ -21,11 +16,11 @@ class TraceASGIMiddleware: self.app = app @staticmethod - async def my_receive(receive: Receive, span: Span): + async def my_receive(receive: Receive, span: Span) -> Receive: await span.request_before() @wraps(receive) - async def my_receive(): + async def my_receive() -> Message: message = await receive() await span.request_after(message) return message diff --git a/ruoyi-fastapi-backend/middlewares/trace_middleware/span.py b/ruoyi-fastapi-backend/middlewares/trace_middleware/span.py index 1e38eab..ef6e46f 100644 --- a/ruoyi-fastapi-backend/middlewares/trace_middleware/span.py +++ b/ruoyi-fastapi-backend/middlewares/trace_middleware/span.py @@ -1,12 +1,8 @@ -# -*- coding: utf-8 -*- -""" -@author: peng -@file: span.py -@time: 2025/1/17 16:57 -""" - +from collections.abc import AsyncGenerator from contextlib import asynccontextmanager -from starlette.types import Scope, Message + +from starlette.types import Message, Scope + from .ctx import TraceCtx @@ -16,16 +12,16 @@ class Span: request(before) --> request(after) --> response(before) --> response(after) """ - def __init__(self, scope: Scope): + def __init__(self, scope: Scope) -> None: self.scope = scope - async def request_before(self): + async def request_before(self) -> None: """ request_before: 处理header信息等, 如记录请求体信息 """ TraceCtx.set_id() - async def request_after(self, message: Message): + async def request_after(self, message: Message) -> Message: """ request_after: 处理请求bytes, 如记录请求参数 @@ -34,7 +30,7 @@ class Span: """ return message - async def response(self, message: Message): + async def response(self, message: Message) -> Message: """ if message['type'] == "http.response.start": -----> request-before pass @@ -48,5 +44,5 @@ class Span: @asynccontextmanager -async def get_current_span(scope: Scope): +async def get_current_span(scope: Scope) -> AsyncGenerator[Span, None]: yield Span(scope) diff --git a/ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py b/ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py index f7e938c..0c48512 100644 --- a/ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py +++ b/ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py @@ -1,16 +1,20 @@ -import httpx import inspect import json -import os import time -from async_lru import alru_cache +from collections.abc import Awaitable from datetime import datetime +from functools import wraps +from typing import Any, Callable, Literal, Optional, TypeVar + +import httpx +from async_lru import alru_cache from fastapi import Request from fastapi.responses import JSONResponse, ORJSONResponse, UJSONResponse -from functools import wraps from sqlalchemy.ext.asyncio import AsyncSession -from typing import Any, Callable, Literal, Optional +from starlette.status import HTTP_200_OK +from typing_extensions import ParamSpec from user_agents import parse + from config.enums import BusinessType from config.env import AppConfig from exceptions.exception import LoginException, ServiceException, ServiceWarning @@ -20,6 +24,9 @@ from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil +P = ParamSpec('P') +R = TypeVar('R') + class Log: """ @@ -31,7 +38,7 @@ class Log: title: str, business_type: BusinessType, log_type: Optional[Literal['login', 'operation']] = 'operation', - ): + ) -> None: """ 日志装饰器 @@ -43,80 +50,39 @@ class Log: self.title = title self.business_type = business_type.value self.log_type = log_type + self._oper_param_len = 2000 - def __call__(self, func): + def __call__(self, func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]: @wraps(func) - async def wrapper(*args, **kwargs): + async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: start_time = time.perf_counter() - # 获取被装饰函数的文件路径 - file_path = inspect.getfile(func) - # 获取项目根路径 - project_root = os.getcwd() - # 处理文件路径,去除项目根路径部分 - relative_path = os.path.relpath(file_path, start=project_root)[0:-2].replace('\\', '.').replace('/', '.') # 获取当前被装饰函数所在路径 - func_path = f'{relative_path}{func.__name__}()' + func_path = self._get_decorator_func_path(func) # 获取上下文信息 request_name_list = get_function_parameters_name_by_type(func, Request) request = get_function_parameters_value_by_name(func, request_name_list[0], *args, **kwargs) - token = request.headers.get('Authorization') session_name_list = get_function_parameters_name_by_type(func, AsyncSession) query_db = get_function_parameters_value_by_name(func, session_name_list[0], *args, **kwargs) request_method = request.method - operator_type = 0 user_agent = request.headers.get('User-Agent') - if 'Windows' in user_agent or 'Macintosh' in user_agent or 'Linux' in user_agent: - operator_type = 1 - if 'Mobile' in user_agent or 'Android' in user_agent or 'iPhone' in user_agent: - operator_type = 2 + # 获取操作类型 + operator_type = self._get_oper_type(user_agent) # 获取请求的url oper_url = request.url.path - # 获取请求的ip及ip归属区域 + # 获取请求ip oper_ip = request.headers.get('X-Forwarded-For') - oper_location = '内网IP' - if AppConfig.app_ip_location_query: - oper_location = await get_ip_location(oper_ip) - # 根据不同的请求类型使用不同的方法获取请求参数 - content_type = request.headers.get('Content-Type') - if content_type and ( - 'multipart/form-data' in content_type or 'application/x-www-form-urlencoded' in content_type - ): - payload = await request.form() - oper_param = '\n'.join([f'{key}: {value}' for key, value in payload.items()]) - else: - payload = await request.body() - # 通过 request.path_params 直接访问路径参数 - path_params = request.path_params - oper_param = {} - if payload: - oper_param.update(json.loads(str(payload, 'utf-8'))) - if path_params: - oper_param.update(path_params) - oper_param = json.dumps(oper_param, ensure_ascii=False) + # 获取请求ip归属区域 + oper_location = await self._get_oper_location(oper_ip) + # 获取请求参数 + oper_param = await self._get_request_params(request) # 日志表请求参数字段长度最大为2000,因此在此处判断长度 - if len(oper_param) > 2000: + if len(oper_param) > self._oper_param_len: oper_param = '请求参数过长' # 获取操作时间 oper_time = datetime.now() # 此处在登录之前向原始函数传递一些登录信息,用于监测在线用户的相关信息 - login_log = {} - if self.log_type == 'login': - user_agent_info = parse(user_agent) - browser = f'{user_agent_info.browser.family}' - system_os = f'{user_agent_info.os.family}' - if user_agent_info.browser.version != (): - browser += f' {user_agent_info.browser.version[0]}' - if user_agent_info.os.version != (): - system_os += f' {user_agent_info.os.version[0]}' - login_log = dict( - ipaddr=oper_ip, - loginLocation=oper_location, - browser=browser, - os=system_os, - loginTime=oper_time.strftime('%Y-%m-%d %H:%M:%S'), - ) - kwargs['form_data'].login_info = login_log + login_log = self._get_login_log(user_agent, oper_ip, oper_location, oper_time, kwargs) try: # 调用原始函数 result = await func(*args, **kwargs) @@ -132,35 +98,12 @@ class Log: # 获取请求耗时 cost_time = float(time.perf_counter() - start_time) * 1000 # 判断请求是否来自api文档 - request_from_swagger = ( - request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False - ) - request_from_redoc = ( - request.headers.get('referer').endswith('redoc') if request.headers.get('referer') else False - ) + request_from_swagger, request_from_redoc = self._is_request_from_swagger_or_redoc(request) # 根据响应结果的类型使用不同的方法获取响应结果参数 - if ( - isinstance(result, JSONResponse) - or isinstance(result, ORJSONResponse) - or isinstance(result, UJSONResponse) - ): - result_dict = json.loads(str(result.body, 'utf-8')) - else: - if request_from_swagger or request_from_redoc: - result_dict = {} - else: - if result.status_code == 200: - result_dict = {'code': result.status_code, 'message': '获取成功'} - else: - result_dict = {'code': result.status_code, 'message': '获取失败'} + result_dict = self._get_result_dict(result, request_from_swagger, request_from_redoc) json_result = json.dumps(result_dict, ensure_ascii=False) # 根据响应结果获取响应状态及异常信息 - status = 1 - error_msg = '' - if result_dict.get('code') == 200: - status = 0 - else: - error_msg = result_dict.get('msg') + status, error_msg = self._get_status_and_error_msg(result_dict) # 根据日志类型向对应的日志表插入数据 if self.log_type == 'login': # 登录请求来自于api文档时不记录登录日志,其余情况则记录 @@ -168,14 +111,18 @@ class Log: pass else: user = kwargs.get('form_data') - user_name = user.username - login_log['loginTime'] = oper_time - login_log['userName'] = user_name - login_log['status'] = str(status) - login_log['msg'] = result_dict.get('msg') + login_log.update( + { + 'loginTime': oper_time, + 'userName': user.username, + 'status': str(status), + 'msg': result_dict.get('msg'), + } + ) await LoginLogService.add_login_log_services(query_db, LogininforModel(**login_log)) else: + token = request.headers.get('Authorization') current_user = await LoginService.get_current_user(request, token, query_db) oper_name = current_user.user.user_name dept_name = current_user.user.dept.dept_name if current_user.user.dept else None @@ -203,9 +150,203 @@ class Log: return wrapper + def _get_decorator_func_path(self, func: Callable) -> str: + """ + 获取被装饰函数所在路径 + + :param func: 被装饰函数 + :return: 被装饰函数所在路径 + """ + # 获取被装饰函数所在的模块 + module = inspect.getmodule(func) + # 获取完整模块路径 + module_path = module.__name__ if module else '' + # 获取当前被装饰函数所在路径 + func_path = f'{module_path}.{func.__name__}()' + + return func_path + + def _get_oper_type(self, user_agent: Any) -> int: + """ + 获取操作类型 + + :param user_agent: 用户代理字符串 + :return: 操作类型 + """ + operator_type = 0 + if 'Windows' in user_agent or 'Macintosh' in user_agent or 'Linux' in user_agent: + operator_type = 1 + if 'Mobile' in user_agent or 'Android' in user_agent or 'iPhone' in user_agent: + operator_type = 2 + + return operator_type + + async def _get_oper_location(self, oper_ip: str) -> str: + """ + 获取请求IP归属区域 + + :param oper_ip: 请求IP + :return: 请求IP归属区域 + """ + oper_location = '内网IP' + if AppConfig.app_ip_location_query: + oper_location = await get_ip_location(oper_ip) + + return oper_location + + async def _get_request_params(self, request: Request) -> str: + """ + 获取请求参数 + + :param request: Request对象 + :return: 格式化后的请求参数字符串 + """ + params = {} + + # 路径和查询参数 + path_params = dict(request.path_params) + query_params = dict(request.query_params) + params.update({k: v for k, v in {'path_params': path_params, 'query_params': query_params}.items() if v}) + + # 请求体处理 + content_type = request.headers.get('Content-Type', '') + + # JSON请求 + if 'application/json' in content_type: + json_body = await request.json() + if json_body: + params['json_body'] = json_body + + # 表单数据 + elif 'multipart/form-data' in content_type or 'application/x-www-form-urlencoded' in content_type: + form_data = await request.form() + if form_data: + # 过滤掉文件对象,只保留普通表单字段 + form_dict = {key: value for key, value in form_data.items() if not hasattr(value, 'filename')} + if form_dict: + params['form_data'] = form_dict + + # 仅在multipart时尝试处理文件 + if 'multipart/form-data' in content_type: + file_info = {} + for key, value in form_data.items(): + if hasattr(value, 'filename'): + file_info[key] = { + 'filename': value.filename, + 'content_type': value.content_type, + 'size': value.size, + 'headers': dict(value.headers), + } + if file_info: + params['files'] = file_info + + # 其他文本请求 + elif 'application/octet-stream' not in content_type: + body = await request.body() + if body: + params['raw_body'] = body.decode('utf-8') + + return json.dumps(params, ensure_ascii=False, indent=2) if params else '' + + def _get_login_log( + self, user_agent: Any, oper_ip: str, oper_location: str, oper_time: datetime, origin_kwargs: dict + ) -> dict: + """ + 获取登录日志信息 + + :param user_agent: 用户代理字符串 + :param oper_ip: 操作ip + :param oper_location: 操作区域 + :param oper_time: 操作时间 + :param origin_kwargs: 原始函数参数 + :return: 登录日志信息 + """ + login_log = {} + if self.log_type == 'login': + user_agent_info = parse(user_agent) + browser = f'{user_agent_info.browser.family}' + system_os = f'{user_agent_info.os.family}' + if user_agent_info.browser.version != (): + browser += f' {user_agent_info.browser.version[0]}' + if user_agent_info.os.version != (): + system_os += f' {user_agent_info.os.version[0]}' + login_log = { + 'ipaddr': oper_ip, + 'loginLocation': oper_location, + 'browser': browser, + 'os': system_os, + 'loginTime': oper_time.strftime('%Y-%m-%d %H:%M:%S'), + } + self._set_login_data(login_log, origin_kwargs) + + return login_log + + def _set_login_data(self, login_log: dict, origin_kwargs: dict) -> None: + """ + 设置登录日志数据 + + :param login_log: 登录日志信息 + :param origin_kwargs: 原始函数参数 + :return: None + """ + if 'form_data' in origin_kwargs: + origin_kwargs['form_data'].login_info = login_log + + def _get_status_and_error_msg(self, result_dict: dict) -> tuple[int, str]: + """ + 获取操作状态和错误信息 + + :param result_dict: 操作结果字典 + :return: 操作状态和错误信息元组 + """ + status = 1 + error_msg = '' + if result_dict.get('code') == HTTP_200_OK: + status = 0 + else: + error_msg = result_dict.get('msg') + + return status, error_msg + + def _is_request_from_swagger_or_redoc(self, request: Request) -> tuple[bool, bool]: + """ + 判断请求是否来自swagger或redoc + + :param request: Request对象 + :return: 是否来自swagger请求和是否来自redoc请求元组 + """ + request_from_swagger = ( + request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False + ) + request_from_redoc = ( + request.headers.get('referer').endswith('redoc') if request.headers.get('referer') else False + ) + + return request_from_swagger, request_from_redoc + + def _get_result_dict(self, result: Any, request_from_swagger: bool, request_from_redoc: bool) -> dict: + """ + 获取操作结果字典 + + :param result: 操作结果 + :param request_from_swagger: 是否来自swagger请求 + :param request_from_redoc: 是否来自redoc请求 + :return: 操作结果字典 + """ + if isinstance(result, (JSONResponse, ORJSONResponse, UJSONResponse)): + result_dict = json.loads(str(result.body, 'utf-8')) + elif request_from_swagger or request_from_redoc: + result_dict = {} + elif result.status_code == HTTP_200_OK: + result_dict = {'code': result.status_code, 'message': '获取成功'} + else: + result_dict = {'code': result.status_code, 'message': '获取失败'} + + return result_dict + @alru_cache() -async def get_ip_location(oper_ip: str): +async def get_ip_location(oper_ip: str) -> str: """ 查询ip归属区域 @@ -214,11 +355,11 @@ async def get_ip_location(oper_ip: str): """ oper_location = '内网IP' try: - if oper_ip != '127.0.0.1' and oper_ip != 'localhost': + if oper_ip not in ['127.0.0.1', 'localhost']: oper_location = '未知' async with httpx.AsyncClient() as client: ip_result = await client.get(f'https://qifu-api.baidubce.com/ip/geo/v1/district?ip={oper_ip}') - if ip_result.status_code == 200: + if ip_result.status_code == HTTP_200_OK: prov = ip_result.json().get('data', {}).get('prov') city = ip_result.json().get('data', {}).get('city') if prov or city: @@ -229,7 +370,7 @@ async def get_ip_location(oper_ip: str): return oper_location -def get_function_parameters_name_by_type(func: Callable, param_type: Any): +def get_function_parameters_name_by_type(func: Callable, param_type: Any) -> list: """ 获取函数指定类型的参数名称 @@ -241,13 +382,23 @@ def get_function_parameters_name_by_type(func: Callable, param_type: Any): parameters = inspect.signature(func).parameters # 找到指定类型的参数名称 parameters_name_list = [] + # 遍历所有参数 for name, param in parameters.items(): - if param.annotation == param_type: + # 处理参数注解 + annotation = param.annotation + # 检查参数类型是否匹配 + # 1. 直接匹配 + # 2. 检查是否为Annotated类型(通过类型名称判断) + if annotation == param_type or ( + hasattr(annotation, '__class__') + and annotation.__class__.__name__ == '_AnnotatedAlias' + and annotation.__origin__ == param_type + ): parameters_name_list.append(name) return parameters_name_list -def get_function_parameters_value_by_name(func: Callable, name: str, *args, **kwargs): +def get_function_parameters_value_by_name(func: Callable, name: str, *args, **kwargs) -> Any: """ 获取函数指定参数的值 diff --git a/ruoyi-fastapi-backend/module_admin/annotation/pydantic_annotation.py b/ruoyi-fastapi-backend/module_admin/annotation/pydantic_annotation.py index 11e8d7f..9dde679 100644 --- a/ruoyi-fastapi-backend/module_admin/annotation/pydantic_annotation.py +++ b/ruoyi-fastapi-backend/module_admin/annotation/pydantic_annotation.py @@ -1,21 +1,23 @@ import inspect +from typing import TYPE_CHECKING, TypeVar + from fastapi import Form, Query from pydantic import BaseModel -from pydantic.fields import FieldInfo -from typing import Type, TypeVar +if TYPE_CHECKING: + from pydantic.fields import FieldInfo BaseModelVar = TypeVar('BaseModelVar', bound=BaseModel) -def as_query(cls: Type[BaseModelVar]) -> Type[BaseModelVar]: +def as_query(cls: type[BaseModelVar]) -> type[BaseModelVar]: """ pydantic模型查询参数装饰器,将pydantic模型用于接收查询参数 """ new_parameters = [] - for field_name, model_field in cls.model_fields.items(): - model_field: FieldInfo # type: ignore + for model_field in cls.model_fields.values(): + model_field: FieldInfo if not model_field.is_required(): new_parameters.append( @@ -36,24 +38,24 @@ def as_query(cls: Type[BaseModelVar]) -> Type[BaseModelVar]: ) ) - async def as_query_func(**data): + async def as_query_func(**data) -> type[BaseModelVar]: return cls(**data) sig = inspect.signature(as_query_func) sig = sig.replace(parameters=new_parameters) - as_query_func.__signature__ = sig # type: ignore - setattr(cls, 'as_query', as_query_func) + as_query_func.__signature__ = sig + cls.as_query = as_query_func return cls -def as_form(cls: Type[BaseModelVar]) -> Type[BaseModelVar]: +def as_form(cls: type[BaseModelVar]) -> type[BaseModelVar]: """ pydantic模型表单参数装饰器,将pydantic模型用于接收表单参数 """ new_parameters = [] - for field_name, model_field in cls.model_fields.items(): - model_field: FieldInfo # type: ignore + for model_field in cls.model_fields.values(): + model_field: FieldInfo if not model_field.is_required(): new_parameters.append( @@ -74,11 +76,11 @@ def as_form(cls: Type[BaseModelVar]) -> Type[BaseModelVar]: ) ) - async def as_form_func(**data): + async def as_form_func(**data) -> type[BaseModelVar]: return cls(**data) sig = inspect.signature(as_form_func) sig = sig.replace(parameters=new_parameters) - as_form_func.__signature__ = sig # type: ignore - setattr(cls, 'as_form', as_form_func) + as_form_func.__signature__ = sig + cls.as_form = as_form_func return cls diff --git a/ruoyi-fastapi-backend/module_admin/aspect/data_scope.py b/ruoyi-fastapi-backend/module_admin/aspect/data_scope.py index 5a7afbb..fe52363 100644 --- a/ruoyi-fastapi-backend/module_admin/aspect/data_scope.py +++ b/ruoyi-fastapi-backend/module_admin/aspect/data_scope.py @@ -1,5 +1,7 @@ -from fastapi import Depends from typing import Optional + +from fastapi import Depends + from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService @@ -21,7 +23,7 @@ class GetDataScope: db_alias: Optional[str] = 'db', user_alias: Optional[str] = 'user_id', dept_alias: Optional[str] = 'dept_id', - ): + ) -> None: """ 获取当前用户数据权限对应的查询sql语句 @@ -35,7 +37,7 @@ class GetDataScope: self.user_alias = user_alias self.dept_alias = dept_alias - def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)) -> str: user_id = current_user.user.user_id dept_id = current_user.user.dept_id custom_data_scope_role_id_list = [ @@ -46,7 +48,7 @@ class GetDataScope: if current_user.user.admin or role.data_scope == self.DATA_SCOPE_ALL: param_sql_list = ['1 == 1'] break - elif role.data_scope == self.DATA_SCOPE_CUSTOM: + if role.data_scope == self.DATA_SCOPE_CUSTOM: if len(custom_data_scope_role_id_list) > 1: param_sql_list.append( f"{self.query_alias}.{self.dept_alias}.in_(select(SysRoleDept.dept_id).where(SysRoleDept.role_id.in_({custom_data_scope_role_id_list}))) if hasattr({self.query_alias}, '{self.dept_alias}') else 1 == 0" @@ -70,6 +72,6 @@ class GetDataScope: else: param_sql_list.append('1 == 0') param_sql_list = list(dict.fromkeys(param_sql_list)) - param_sql = f"or_({', '.join(param_sql_list)})" + param_sql = f'or_({", ".join(param_sql_list)})' return param_sql diff --git a/ruoyi-fastapi-backend/module_admin/aspect/interface_auth.py b/ruoyi-fastapi-backend/module_admin/aspect/interface_auth.py index 8f8349d..db81952 100644 --- a/ruoyi-fastapi-backend/module_admin/aspect/interface_auth.py +++ b/ruoyi-fastapi-backend/module_admin/aspect/interface_auth.py @@ -1,5 +1,7 @@ +from typing import Union + from fastapi import Depends -from typing import List, Union + from exceptions.exception import PermissionException from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService @@ -10,7 +12,7 @@ class CheckUserInterfaceAuth: 校验当前用户是否具有相应的接口权限 """ - def __init__(self, perm: Union[str, List], is_strict: bool = False): + def __init__(self, perm: Union[str, list], is_strict: bool = False) -> None: """ 校验当前用户是否具有相应的接口权限 @@ -20,20 +22,18 @@ class CheckUserInterfaceAuth: self.perm = perm self.is_strict = is_strict - def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)) -> bool: user_auth_list = current_user.permissions if '*:*:*' in user_auth_list: return True - if isinstance(self.perm, str): - if self.perm in user_auth_list: - return True + if isinstance(self.perm, str) and self.perm in user_auth_list: + return True if isinstance(self.perm, list): if self.is_strict: - if all([perm_str in user_auth_list for perm_str in self.perm]): - return True - else: - if any([perm_str in user_auth_list for perm_str in self.perm]): + if all(perm_str in user_auth_list for perm_str in self.perm): return True + elif any(perm_str in user_auth_list for perm_str in self.perm): + return True raise PermissionException(data='', message='该用户无此接口权限') @@ -42,7 +42,7 @@ class CheckRoleInterfaceAuth: 根据角色校验当前用户是否具有相应的接口权限 """ - def __init__(self, role_key: Union[str, List], is_strict: bool = False): + def __init__(self, role_key: Union[str, list], is_strict: bool = False) -> None: """ 根据角色校验当前用户是否具有相应的接口权限 @@ -52,17 +52,15 @@ class CheckRoleInterfaceAuth: self.role_key = role_key self.is_strict = is_strict - def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): + def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)) -> bool: user_role_list = current_user.user.role user_role_key_list = [role.role_key for role in user_role_list] - if isinstance(self.role_key, str): - if self.role_key in user_role_key_list: - return True + if isinstance(self.role_key, str) and self.role_key in user_role_key_list: + return True if isinstance(self.role_key, list): if self.is_strict: - if all([role_key_str in user_role_key_list for role_key_str in self.role_key]): - return True - else: - if any([role_key_str in user_role_key_list for role_key_str in self.role_key]): + if all(role_key_str in user_role_key_list for role_key_str in self.role_key): return True + elif any(role_key_str in user_role_key_list for role_key_str in self.role_key): + return True raise PermissionException(data='', message='该用户无此接口权限') diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index 9e72713..7ade706 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -1,5 +1,7 @@ -from fastapi import APIRouter, Depends, Request -from typing import List +from typing import Annotated + +from fastapi import APIRouter, Depends, Path, Request, Response + from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.service.cache_service import CacheService @@ -7,14 +9,13 @@ from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil - -cacheController = APIRouter(prefix='/monitor/cache', dependencies=[Depends(LoginService.get_current_user)]) +cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[Depends(LoginService.get_current_user)]) -@cacheController.get( +@cache_controller.get( '', response_model=CacheMonitorModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))] ) -async def get_monitor_cache_info(request: Request): +async def get_monitor_cache_info(request: Request) -> Response: # 获取全量数据 cache_info_query_result = await CacheService.get_cache_monitor_statistical_info_services(request) logger.info('获取成功') @@ -22,12 +23,12 @@ async def get_monitor_cache_info(request: Request): return ResponseUtil.success(data=cache_info_query_result) -@cacheController.get( +@cache_controller.get( '/getNames', - response_model=List[CacheInfoModel], + response_model=list[CacheInfoModel], dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))], ) -async def get_monitor_cache_name(request: Request): +async def get_monitor_cache_name(request: Request) -> Response: # 获取全量数据 cache_name_list_result = await CacheService.get_cache_monitor_cache_name_services() logger.info('获取成功') @@ -35,12 +36,12 @@ async def get_monitor_cache_name(request: Request): return ResponseUtil.success(data=cache_name_list_result) -@cacheController.get( +@cache_controller.get( '/getKeys/{cache_name}', - response_model=List[str], + response_model=list[str], dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))], ) -async def get_monitor_cache_key(request: Request, cache_name: str): +async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Path(description='缓存名称')]) -> Response: # 获取全量数据 cache_key_list_result = await CacheService.get_cache_monitor_cache_key_services(request, cache_name) logger.info('获取成功') @@ -48,12 +49,16 @@ async def get_monitor_cache_key(request: Request, cache_name: str): return ResponseUtil.success(data=cache_key_list_result) -@cacheController.get( +@cache_controller.get( '/getValue/{cache_name}/{cache_key}', response_model=CacheInfoModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))], ) -async def get_monitor_cache_value(request: Request, cache_name: str, cache_key: str): +async def get_monitor_cache_value( + request: Request, + cache_name: Annotated[str, Path(description='缓存名称')], + cache_key: Annotated[str, Path(description='缓存键')], +) -> Response: # 获取全量数据 cache_value_list_result = await CacheService.get_cache_monitor_cache_value_services(request, cache_name, cache_key) logger.info('获取成功') @@ -61,28 +66,30 @@ async def get_monitor_cache_value(request: Request, cache_name: str, cache_key: return ResponseUtil.success(data=cache_value_list_result) -@cacheController.delete( +@cache_controller.delete( '/clearCacheName/{cache_name}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))] ) -async def clear_monitor_cache_name(request: Request, cache_name: str): +async def clear_monitor_cache_name( + request: Request, cache_name: Annotated[str, Path(description='缓存名称')] +) -> Response: clear_cache_name_result = await CacheService.clear_cache_monitor_cache_name_services(request, cache_name) logger.info(clear_cache_name_result.message) return ResponseUtil.success(msg=clear_cache_name_result.message) -@cacheController.delete( +@cache_controller.delete( '/clearCacheKey/{cache_key}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))] ) -async def clear_monitor_cache_key(request: Request, cache_key: str): +async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Path(description='缓存键')]) -> Response: clear_cache_key_result = await CacheService.clear_cache_monitor_cache_key_services(request, cache_key) logger.info(clear_cache_key_result.message) return ResponseUtil.success(msg=clear_cache_key_result.message) -@cacheController.delete('/clearCacheAll', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))]) -async def clear_monitor_cache_all(request: Request): +@cache_controller.delete('/clearCacheAll', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))]) +async def clear_monitor_cache_all(request: Request) -> Response: clear_cache_all_result = await CacheService.clear_cache_monitor_all_services(request) logger.info(clear_cache_all_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py index 83d35b8..479375c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py @@ -1,28 +1,24 @@ import uuid from datetime import timedelta -from fastapi import APIRouter, Request + +from fastapi import APIRouter, Request, Response + from config.enums import RedisInitKeyConfig from module_admin.entity.vo.login_vo import CaptchaCode from module_admin.service.captcha_service import CaptchaService -from utils.response_util import ResponseUtil from utils.log_util import logger +from utils.response_util import ResponseUtil + +captcha_controller = APIRouter() -captchaController = APIRouter() - - -@captchaController.get('/captchaImage') -async def get_captcha_image(request: Request): +@captcha_controller.get('/captchaImage') +async def get_captcha_image(request: Request) -> Response: captcha_enabled = ( - True - if await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') - == 'true' - else False + await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true' ) register_enabled = ( - True - if await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.registerUser') == 'true' - else False + await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.registerUser') == 'true' ) session_id = str(uuid.uuid4()) captcha_result = await CaptchaService.create_captcha_image_service() diff --git a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py index d2fd621..714ecbd 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py @@ -1,35 +1,38 @@ -from fastapi import APIRouter, BackgroundTasks, Depends, File, Query, Request, UploadFile +from typing import Annotated + +from fastapi import APIRouter, BackgroundTasks, Depends, File, Query, Request, Response, UploadFile + from module_admin.service.common_service import CommonService from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil -commonController = APIRouter(prefix='/common', dependencies=[Depends(LoginService.get_current_user)]) +common_controller = APIRouter(prefix='/common', dependencies=[Depends(LoginService.get_current_user)]) -@commonController.post('/upload') -async def common_upload(request: Request, file: UploadFile = File(...)): +@common_controller.post('/upload') +async def common_upload(request: Request, file: Annotated[UploadFile, File(...)]) -> Response: upload_result = await CommonService.upload_service(request, file) logger.info('上传成功') return ResponseUtil.success(model_content=upload_result.result) -@commonController.get('/download') +@common_controller.get('/download') async def common_download( request: Request, background_tasks: BackgroundTasks, - file_name: str = Query(alias='fileName'), - delete: bool = Query(), -): + file_name: Annotated[str, Query(alias='fileName')], + delete: Annotated[bool, Query()], +) -> Response: download_result = await CommonService.download_services(background_tasks, file_name, delete) logger.info(download_result.message) return ResponseUtil.streaming(data=download_result.result) -@commonController.get('/download/resource') -async def common_download_resource(request: Request, resource: str = Query()): +@common_controller.get('/download/resource') +async def common_download_resource(request: Request, resource: Annotated[str, Query()]) -> Response: download_resource_result = await CommonService.download_resource_services(resource) logger.info(download_resource_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index 747dff2..640966c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -1,7 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -15,18 +18,17 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -configController = APIRouter(prefix='/system/config', dependencies=[Depends(LoginService.get_current_user)]) +config_controller = APIRouter(prefix='/system/config', dependencies=[Depends(LoginService.get_current_user)]) -@configController.get( +@config_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:config:list'))] ) async def get_system_config_list( request: Request, - config_page_query: ConfigPageQueryModel = Depends(ConfigPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + config_page_query: Annotated[ConfigPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 config_page_query_result = await ConfigService.get_config_list_services(query_db, config_page_query, is_page=True) logger.info('获取成功') @@ -34,15 +36,15 @@ async def get_system_config_list( return ResponseUtil.success(model_content=config_page_query_result) -@configController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:config:add'))]) +@config_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:config:add'))]) @ValidateFields(validate_model='add_config') @Log(title='参数管理', business_type=BusinessType.INSERT) async def add_system_config( request: Request, add_config: ConfigModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_config.create_by = current_user.user.user_name add_config.create_time = datetime.now() add_config.update_by = current_user.user.user_name @@ -53,15 +55,15 @@ async def add_system_config( return ResponseUtil.success(msg=add_config_result.message) -@configController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:config:edit'))]) +@config_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:config:edit'))]) @ValidateFields(validate_model='edit_config') @Log(title='参数管理', business_type=BusinessType.UPDATE) async def edit_system_config( request: Request, edit_config: ConfigModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_config.update_by = current_user.user.user_name edit_config.update_time = datetime.now() edit_config_result = await ConfigService.edit_config_services(request, query_db, edit_config) @@ -70,18 +72,25 @@ async def edit_system_config( return ResponseUtil.success(msg=edit_config_result.message) -@configController.delete('/refreshCache', dependencies=[Depends(CheckUserInterfaceAuth('system:config:remove'))]) +@config_controller.delete('/refreshCache', dependencies=[Depends(CheckUserInterfaceAuth('system:config:remove'))]) @Log(title='参数管理', business_type=BusinessType.UPDATE) -async def refresh_system_config(request: Request, query_db: AsyncSession = Depends(get_db)): +async def refresh_system_config( + request: Request, + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: refresh_config_result = await ConfigService.refresh_sys_config_services(request, query_db) logger.info(refresh_config_result.message) return ResponseUtil.success(msg=refresh_config_result.message) -@configController.delete('/{config_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:config:remove'))]) +@config_controller.delete('/{config_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:config:remove'))]) @Log(title='参数管理', business_type=BusinessType.DELETE) -async def delete_system_config(request: Request, config_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_config( + request: Request, + config_ids: Annotated[str, Path(description='需要删除的参数主键')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_config = DeleteConfigModel(configIds=config_ids) delete_config_result = await ConfigService.delete_config_services(request, query_db, delete_config) logger.info(delete_config_result.message) @@ -89,18 +98,22 @@ async def delete_system_config(request: Request, config_ids: str, query_db: Asyn return ResponseUtil.success(msg=delete_config_result.message) -@configController.get( +@config_controller.get( '/{config_id}', response_model=ConfigModel, dependencies=[Depends(CheckUserInterfaceAuth('system:config:query'))] ) -async def query_detail_system_config(request: Request, config_id: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_config( + request: Request, + config_id: Annotated[int, Path(description='参数主键')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: config_detail_result = await ConfigService.config_detail_services(query_db, config_id) logger.info(f'获取config_id为{config_id}的信息成功') return ResponseUtil.success(data=config_detail_result) -@configController.get('/configKey/{config_key}') -async def query_system_config(request: Request, config_key: str): +@config_controller.get('/configKey/{config_key}') +async def query_system_config(request: Request, config_key: str) -> Response: # 获取全量数据 config_query_result = await ConfigService.query_config_list_from_cache_services(request.app.state.redis, config_key) logger.info('获取成功') @@ -108,13 +121,13 @@ async def query_system_config(request: Request, config_key: str): return ResponseUtil.success(msg=config_query_result) -@configController.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:config:export'))]) +@config_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:config:export'))]) @Log(title='参数管理', business_type=BusinessType.EXPORT) async def export_system_config_list( request: Request, - config_page_query: ConfigPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + config_page_query: Annotated[ConfigPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 config_query_result = await ConfigService.get_config_list_services(query_db, config_page_query, is_page=False) config_export_result = await ConfigService.export_config_list_services(config_query_result) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index 2943206..d5638c7 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -1,8 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -15,21 +17,20 @@ from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil - -deptController = APIRouter(prefix='/system/dept', dependencies=[Depends(LoginService.get_current_user)]) +dept_controller = APIRouter(prefix='/system/dept', dependencies=[Depends(LoginService.get_current_user)]) -@deptController.get( +@dept_controller.get( '/list/exclude/{dept_id}', - response_model=List[DeptModel], + response_model=list[DeptModel], dependencies=[Depends(CheckUserInterfaceAuth('system:dept:list'))], ) async def get_system_dept_tree_for_edit_option( request: Request, - dept_id: int, - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + dept_id: Annotated[int, Path(description='部门id')], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: dept_query = DeptModel(deptId=dept_id) dept_query_result = await DeptService.get_dept_for_edit_option_services(query_db, dept_query, data_scope_sql) logger.info('获取成功') @@ -37,30 +38,30 @@ async def get_system_dept_tree_for_edit_option( return ResponseUtil.success(data=dept_query_result) -@deptController.get( - '/list', response_model=List[DeptModel], dependencies=[Depends(CheckUserInterfaceAuth('system:dept:list'))] +@dept_controller.get( + '/list', response_model=list[DeptModel], dependencies=[Depends(CheckUserInterfaceAuth('system:dept:list'))] ) async def get_system_dept_list( request: Request, - dept_query: DeptQueryModel = Depends(DeptQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + dept_query: Annotated[DeptQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: dept_query_result = await DeptService.get_dept_list_services(query_db, dept_query, data_scope_sql) logger.info('获取成功') return ResponseUtil.success(data=dept_query_result) -@deptController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:add'))]) +@dept_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:add'))]) @ValidateFields(validate_model='add_dept') @Log(title='部门管理', business_type=BusinessType.INSERT) async def add_system_dept( request: Request, add_dept: DeptModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_dept.create_by = current_user.user.user_name add_dept.create_time = datetime.now() add_dept.update_by = current_user.user.user_name @@ -71,16 +72,16 @@ async def add_system_dept( return ResponseUtil.success(data=add_dept_result) -@deptController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:edit'))]) +@dept_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:edit'))]) @ValidateFields(validate_model='edit_dept') @Log(title='部门管理', business_type=BusinessType.UPDATE) async def edit_system_dept( request: Request, edit_dept: DeptModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: if not current_user.user.admin: await DeptService.check_dept_data_scope_services(query_db, edit_dept.dept_id, data_scope_sql) edit_dept.update_by = current_user.user.user_name @@ -91,15 +92,15 @@ async def edit_system_dept( return ResponseUtil.success(msg=edit_dept_result.message) -@deptController.delete('/{dept_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:remove'))]) +@dept_controller.delete('/{dept_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:remove'))]) @Log(title='部门管理', business_type=BusinessType.DELETE) async def delete_system_dept( request: Request, - dept_ids: str, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + dept_ids: Annotated[str, Path(description='需要删除的部门id')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: dept_id_list = dept_ids.split(',') if dept_ids else [] if dept_id_list: for dept_id in dept_id_list: @@ -114,16 +115,16 @@ async def delete_system_dept( return ResponseUtil.success(msg=delete_dept_result.message) -@deptController.get( +@dept_controller.get( '/{dept_id}', response_model=DeptModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dept:query'))] ) async def query_detail_system_dept( request: Request, - dept_id: int, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + dept_id: Annotated[int, Path(description='部门id')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: if not current_user.user.admin: await DeptService.check_dept_data_scope_services(query_db, dept_id, data_scope_sql) detail_dept_result = await DeptService.dept_detail_services(query_db, dept_id) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index 27fa24c..2822591 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -1,8 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -23,18 +25,17 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -dictController = APIRouter(prefix='/system/dict', dependencies=[Depends(LoginService.get_current_user)]) +dict_controller = APIRouter(prefix='/system/dict', dependencies=[Depends(LoginService.get_current_user)]) -@dictController.get( +@dict_controller.get( '/type/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:list'))] ) async def get_system_dict_type_list( request: Request, - dict_type_page_query: DictTypePageQueryModel = Depends(DictTypePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + dict_type_page_query: Annotated[DictTypePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 dict_type_page_query_result = await DictTypeService.get_dict_type_list_services( query_db, dict_type_page_query, is_page=True @@ -44,15 +45,15 @@ async def get_system_dict_type_list( return ResponseUtil.success(model_content=dict_type_page_query_result) -@dictController.post('/type', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:add'))]) +@dict_controller.post('/type', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:add'))]) @ValidateFields(validate_model='add_dict_type') @Log(title='字典类型', business_type=BusinessType.INSERT) async def add_system_dict_type( request: Request, add_dict_type: DictTypeModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_dict_type.create_by = current_user.user.user_name add_dict_type.create_time = datetime.now() add_dict_type.update_by = current_user.user.user_name @@ -63,15 +64,15 @@ async def add_system_dict_type( return ResponseUtil.success(msg=add_dict_type_result.message) -@dictController.put('/type', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:edit'))]) +@dict_controller.put('/type', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:edit'))]) @ValidateFields(validate_model='edit_dict_type') @Log(title='字典类型', business_type=BusinessType.UPDATE) async def edit_system_dict_type( request: Request, edit_dict_type: DictTypeModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_dict_type.update_by = current_user.user.user_name edit_dict_type.update_time = datetime.now() edit_dict_type_result = await DictTypeService.edit_dict_type_services(request, query_db, edit_dict_type) @@ -80,18 +81,22 @@ async def edit_system_dict_type( return ResponseUtil.success(msg=edit_dict_type_result.message) -@dictController.delete('/type/refreshCache', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) +@dict_controller.delete('/type/refreshCache', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) @Log(title='字典类型', business_type=BusinessType.UPDATE) -async def refresh_system_dict(request: Request, query_db: AsyncSession = Depends(get_db)): +async def refresh_system_dict(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: refresh_dict_result = await DictTypeService.refresh_sys_dict_services(request, query_db) logger.info(refresh_dict_result.message) return ResponseUtil.success(msg=refresh_dict_result.message) -@dictController.delete('/type/{dict_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) +@dict_controller.delete('/type/{dict_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) @Log(title='字典类型', business_type=BusinessType.DELETE) -async def delete_system_dict_type(request: Request, dict_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_dict_type( + request: Request, + dict_ids: Annotated[str, Path(description='需要删除的字典主键')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_dict_type = DeleteDictTypeModel(dictIds=dict_ids) delete_dict_type_result = await DictTypeService.delete_dict_type_services(request, query_db, delete_dict_type) logger.info(delete_dict_type_result.message) @@ -99,33 +104,39 @@ async def delete_system_dict_type(request: Request, dict_ids: str, query_db: Asy return ResponseUtil.success(msg=delete_dict_type_result.message) -@dictController.get('/type/optionselect', response_model=List[DictTypeModel]) -async def query_system_dict_type_options(request: Request, query_db: AsyncSession = Depends(get_db)): +@dict_controller.get('/type/optionselect', response_model=list[DictTypeModel]) +async def query_system_dict_type_options( + request: Request, query_db: Annotated[AsyncSession, Depends(get_db)] +) -> Response: dict_type_query_result = await DictTypeService.get_dict_type_list_services( - query_db, DictTypePageQueryModel(**dict()), is_page=False + query_db, DictTypePageQueryModel(), is_page=False ) logger.info('获取成功') return ResponseUtil.success(data=dict_type_query_result) -@dictController.get( +@dict_controller.get( '/type/{dict_id}', response_model=DictTypeModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:query'))] ) -async def query_detail_system_dict_type(request: Request, dict_id: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_dict_type( + request: Request, + dict_id: Annotated[int, Path(description='字典主键')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: dict_type_detail_result = await DictTypeService.dict_type_detail_services(query_db, dict_id) logger.info(f'获取dict_id为{dict_id}的信息成功') return ResponseUtil.success(data=dict_type_detail_result) -@dictController.post('/type/export', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:export'))]) +@dict_controller.post('/type/export', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:export'))]) @Log(title='字典类型', business_type=BusinessType.EXPORT) async def export_system_dict_type_list( request: Request, - dict_type_page_query: DictTypePageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + dict_type_page_query: Annotated[DictTypePageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 dict_type_query_result = await DictTypeService.get_dict_type_list_services( query_db, dict_type_page_query, is_page=False @@ -136,8 +147,12 @@ async def export_system_dict_type_list( return ResponseUtil.streaming(data=bytes2file_response(dict_type_export_result)) -@dictController.get('/data/type/{dict_type}') -async def query_system_dict_type_data(request: Request, dict_type: str, query_db: AsyncSession = Depends(get_db)): +@dict_controller.get('/data/type/{dict_type}') +async def query_system_dict_type_data( + request: Request, + dict_type: Annotated[str, Path(description='字典类型')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 dict_data_query_result = await DictDataService.query_dict_data_list_from_cache_services( request.app.state.redis, dict_type @@ -147,14 +162,14 @@ async def query_system_dict_type_data(request: Request, dict_type: str, query_db return ResponseUtil.success(data=dict_data_query_result) -@dictController.get( +@dict_controller.get( '/data/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:list'))] ) async def get_system_dict_data_list( request: Request, - dict_data_page_query: DictDataPageQueryModel = Depends(DictDataPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + dict_data_page_query: Annotated[DictDataPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 dict_data_page_query_result = await DictDataService.get_dict_data_list_services( query_db, dict_data_page_query, is_page=True @@ -164,15 +179,15 @@ async def get_system_dict_data_list( return ResponseUtil.success(model_content=dict_data_page_query_result) -@dictController.post('/data', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:add'))]) +@dict_controller.post('/data', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:add'))]) @ValidateFields(validate_model='add_dict_data') @Log(title='字典数据', business_type=BusinessType.INSERT) async def add_system_dict_data( request: Request, add_dict_data: DictDataModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_dict_data.create_by = current_user.user.user_name add_dict_data.create_time = datetime.now() add_dict_data.update_by = current_user.user.user_name @@ -183,15 +198,15 @@ async def add_system_dict_data( return ResponseUtil.success(msg=add_dict_data_result.message) -@dictController.put('/data', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:edit'))]) +@dict_controller.put('/data', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:edit'))]) @ValidateFields(validate_model='edit_dict_data') @Log(title='字典数据', business_type=BusinessType.UPDATE) async def edit_system_dict_data( request: Request, edit_dict_data: DictDataModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_dict_data.update_by = current_user.user.user_name edit_dict_data.update_time = datetime.now() edit_dict_data_result = await DictDataService.edit_dict_data_services(request, query_db, edit_dict_data) @@ -200,9 +215,13 @@ async def edit_system_dict_data( return ResponseUtil.success(msg=edit_dict_data_result.message) -@dictController.delete('/data/{dict_codes}', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) +@dict_controller.delete('/data/{dict_codes}', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) @Log(title='字典数据', business_type=BusinessType.DELETE) -async def delete_system_dict_data(request: Request, dict_codes: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_dict_data( + request: Request, + dict_codes: Annotated[str, Path(description='需要删除的字典编码')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_dict_data = DeleteDictDataModel(dictCodes=dict_codes) delete_dict_data_result = await DictDataService.delete_dict_data_services(request, query_db, delete_dict_data) logger.info(delete_dict_data_result.message) @@ -210,25 +229,29 @@ async def delete_system_dict_data(request: Request, dict_codes: str, query_db: A return ResponseUtil.success(msg=delete_dict_data_result.message) -@dictController.get( +@dict_controller.get( '/data/{dict_code}', response_model=DictDataModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:query'))], ) -async def query_detail_system_dict_data(request: Request, dict_code: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_dict_data( + request: Request, + dict_code: Annotated[int, Path(description='字典编码')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: detail_dict_data_result = await DictDataService.dict_data_detail_services(query_db, dict_code) logger.info(f'获取dict_code为{dict_code}的信息成功') return ResponseUtil.success(data=detail_dict_data_result) -@dictController.post('/data/export', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:export'))]) +@dict_controller.post('/data/export', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:export'))]) @Log(title='字典数据', business_type=BusinessType.EXPORT) async def export_system_dict_data_list( request: Request, - dict_data_page_query: DictDataPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + dict_data_page_query: Annotated[DictDataPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 dict_data_query_result = await DictDataService.get_dict_data_list_services( query_db, dict_data_page_query, is_page=False diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index c930569..0b4306d 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -1,7 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -23,18 +26,17 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -jobController = APIRouter(prefix='/monitor', dependencies=[Depends(LoginService.get_current_user)]) +job_controller = APIRouter(prefix='/monitor', dependencies=[Depends(LoginService.get_current_user)]) -@jobController.get( +@job_controller.get( '/job/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:list'))] ) async def get_system_job_list( request: Request, - job_page_query: JobPageQueryModel = Depends(JobPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + job_page_query: Annotated[JobPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 notice_page_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=True) logger.info('获取成功') @@ -42,15 +44,15 @@ async def get_system_job_list( return ResponseUtil.success(model_content=notice_page_query_result) -@jobController.post('/job', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:add'))]) +@job_controller.post('/job', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:add'))]) @ValidateFields(validate_model='add_job') @Log(title='定时任务', business_type=BusinessType.INSERT) async def add_system_job( request: Request, add_job: JobModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_job.create_by = current_user.user.user_name add_job.create_time = datetime.now() add_job.update_by = current_user.user.user_name @@ -61,15 +63,15 @@ async def add_system_job( return ResponseUtil.success(msg=add_job_result.message) -@jobController.put('/job', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:edit'))]) +@job_controller.put('/job', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:edit'))]) @ValidateFields(validate_model='edit_job') @Log(title='定时任务', business_type=BusinessType.UPDATE) async def edit_system_job( request: Request, edit_job: EditJobModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_job.update_by = current_user.user.user_name edit_job.update_time = datetime.now() edit_job_result = await JobService.edit_job_services(query_db, edit_job) @@ -78,14 +80,14 @@ async def edit_system_job( return ResponseUtil.success(msg=edit_job_result.message) -@jobController.put('/job/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:changeStatus'))]) +@job_controller.put('/job/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:changeStatus'))]) @Log(title='定时任务', business_type=BusinessType.UPDATE) async def change_system_job_status( request: Request, change_job: EditJobModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_job = EditJobModel( jobId=change_job.job_id, status=change_job.status, @@ -99,18 +101,26 @@ async def change_system_job_status( return ResponseUtil.success(msg=edit_job_result.message) -@jobController.put('/job/run', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:changeStatus'))]) +@job_controller.put('/job/run', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:changeStatus'))]) @Log(title='定时任务', business_type=BusinessType.UPDATE) -async def execute_system_job(request: Request, execute_job: JobModel, query_db: AsyncSession = Depends(get_db)): +async def execute_system_job( + request: Request, + execute_job: JobModel, + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: execute_job_result = await JobService.execute_job_once_services(query_db, execute_job) logger.info(execute_job_result.message) return ResponseUtil.success(msg=execute_job_result.message) -@jobController.delete('/job/{job_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) +@job_controller.delete('/job/{job_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) @Log(title='定时任务', business_type=BusinessType.DELETE) -async def delete_system_job(request: Request, job_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_job( + request: Request, + job_ids: Annotated[str, Path(description='需要删除的定时任务ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_job = DeleteJobModel(jobIds=job_ids) delete_job_result = await JobService.delete_job_services(query_db, delete_job) logger.info(delete_job_result.message) @@ -118,23 +128,27 @@ async def delete_system_job(request: Request, job_ids: str, query_db: AsyncSessi return ResponseUtil.success(msg=delete_job_result.message) -@jobController.get( +@job_controller.get( '/job/{job_id}', response_model=JobModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:query'))] ) -async def query_detail_system_job(request: Request, job_id: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_job( + request: Request, + job_id: Annotated[int, Path(description='任务ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: job_detail_result = await JobService.job_detail_services(query_db, job_id) logger.info(f'获取job_id为{job_id}的信息成功') return ResponseUtil.success(data=job_detail_result) -@jobController.post('/job/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:export'))]) +@job_controller.post('/job/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:export'))]) @Log(title='定时任务', business_type=BusinessType.EXPORT) async def export_system_job_list( request: Request, - job_page_query: JobPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + job_page_query: Annotated[JobPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 job_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=False) job_export_result = await JobService.export_job_list_services(request, job_query_result) @@ -143,14 +157,14 @@ async def export_system_job_list( return ResponseUtil.streaming(data=bytes2file_response(job_export_result)) -@jobController.get( +@job_controller.get( '/jobLog/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:list'))] ) async def get_system_job_log_list( request: Request, - job_log_page_query: JobLogPageQueryModel = Depends(JobLogPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + job_log_page_query: Annotated[JobLogPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 job_log_page_query_result = await JobLogService.get_job_log_list_services( query_db, job_log_page_query, is_page=True @@ -160,18 +174,25 @@ async def get_system_job_log_list( return ResponseUtil.success(model_content=job_log_page_query_result) -@jobController.delete('/jobLog/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) +@job_controller.delete('/jobLog/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) @Log(title='定时任务调度日志', business_type=BusinessType.CLEAN) -async def clear_system_job_log(request: Request, query_db: AsyncSession = Depends(get_db)): +async def clear_system_job_log( + request: Request, + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: clear_job_log_result = await JobLogService.clear_job_log_services(query_db) logger.info(clear_job_log_result.message) return ResponseUtil.success(msg=clear_job_log_result.message) -@jobController.delete('/jobLog/{job_log_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) +@job_controller.delete('/jobLog/{job_log_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) @Log(title='定时任务调度日志', business_type=BusinessType.DELETE) -async def delete_system_job_log(request: Request, job_log_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_job_log( + request: Request, + job_log_ids: Annotated[str, Path(description='需要删除的定时任务日志ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_job_log = DeleteJobLogModel(jobLogIds=job_log_ids) delete_job_log_result = await JobLogService.delete_job_log_services(query_db, delete_job_log) logger.info(delete_job_log_result.message) @@ -179,13 +200,13 @@ async def delete_system_job_log(request: Request, job_log_ids: str, query_db: As return ResponseUtil.success(msg=delete_job_log_result.message) -@jobController.post('/jobLog/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:export'))]) +@job_controller.post('/jobLog/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:export'))]) @Log(title='定时任务调度日志', business_type=BusinessType.EXPORT) async def export_system_job_log_list( request: Request, - job_log_page_query: JobLogPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + job_log_page_query: Annotated[JobLogPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 job_log_query_result = await JobLogService.get_job_log_list_services(query_db, job_log_page_query, is_page=False) job_log_export_result = await JobLogService.export_job_log_list_services(request, job_log_query_result) diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index a01ba94..39541be 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -1,5 +1,8 @@ -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -18,20 +21,19 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -logController = APIRouter(prefix='/monitor', dependencies=[Depends(LoginService.get_current_user)]) +log_controller = APIRouter(prefix='/monitor', dependencies=[Depends(LoginService.get_current_user)]) -@logController.get( +@log_controller.get( '/operlog/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:list'))], ) async def get_system_operation_log_list( request: Request, - operation_log_page_query: OperLogPageQueryModel = Depends(OperLogPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + operation_log_page_query: Annotated[OperLogPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 operation_log_page_query_result = await OperationLogService.get_operation_log_list_services( query_db, operation_log_page_query, is_page=True @@ -41,18 +43,22 @@ async def get_system_operation_log_list( return ResponseUtil.success(model_content=operation_log_page_query_result) -@logController.delete('/operlog/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:remove'))]) +@log_controller.delete('/operlog/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:remove'))]) @Log(title='操作日志', business_type=BusinessType.CLEAN) -async def clear_system_operation_log(request: Request, query_db: AsyncSession = Depends(get_db)): +async def clear_system_operation_log(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: clear_operation_log_result = await OperationLogService.clear_operation_log_services(query_db) logger.info(clear_operation_log_result.message) return ResponseUtil.success(msg=clear_operation_log_result.message) -@logController.delete('/operlog/{oper_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:remove'))]) +@log_controller.delete('/operlog/{oper_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:remove'))]) @Log(title='操作日志', business_type=BusinessType.DELETE) -async def delete_system_operation_log(request: Request, oper_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_operation_log( + request: Request, + oper_ids: Annotated[str, Path(description='需要删除的日志主键')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_operation_log = DeleteOperLogModel(operIds=oper_ids) delete_operation_log_result = await OperationLogService.delete_operation_log_services( query_db, delete_operation_log @@ -62,13 +68,13 @@ async def delete_system_operation_log(request: Request, oper_ids: str, query_db: return ResponseUtil.success(msg=delete_operation_log_result.message) -@logController.post('/operlog/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:export'))]) +@log_controller.post('/operlog/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:export'))]) @Log(title='操作日志', business_type=BusinessType.EXPORT) async def export_system_operation_log_list( request: Request, - operation_log_page_query: OperLogPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + operation_log_page_query: Annotated[OperLogPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 operation_log_query_result = await OperationLogService.get_operation_log_list_services( query_db, operation_log_page_query, is_page=False @@ -81,16 +87,16 @@ async def export_system_operation_log_list( return ResponseUtil.streaming(data=bytes2file_response(operation_log_export_result)) -@logController.get( +@log_controller.get( '/logininfor/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:list'))], ) async def get_system_login_log_list( request: Request, - login_log_page_query: LoginLogPageQueryModel = Depends(LoginLogPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + login_log_page_query: Annotated[LoginLogPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 login_log_page_query_result = await LoginLogService.get_login_log_list_services( query_db, login_log_page_query, is_page=True @@ -100,20 +106,24 @@ async def get_system_login_log_list( return ResponseUtil.success(model_content=login_log_page_query_result) -@logController.delete('/logininfor/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:remove'))]) +@log_controller.delete('/logininfor/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:remove'))]) @Log(title='登录日志', business_type=BusinessType.CLEAN) -async def clear_system_login_log(request: Request, query_db: AsyncSession = Depends(get_db)): +async def clear_system_login_log(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: clear_login_log_result = await LoginLogService.clear_login_log_services(query_db) logger.info(clear_login_log_result.message) return ResponseUtil.success(msg=clear_login_log_result.message) -@logController.delete( +@log_controller.delete( '/logininfor/{info_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:remove'))] ) @Log(title='登录日志', business_type=BusinessType.DELETE) -async def delete_system_login_log(request: Request, info_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_login_log( + request: Request, + info_ids: Annotated[str, Path(description='需要删除的访问ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_login_log = DeleteLoginLogModel(infoIds=info_ids) delete_login_log_result = await LoginLogService.delete_login_log_services(query_db, delete_login_log) logger.info(delete_login_log_result.message) @@ -121,11 +131,15 @@ async def delete_system_login_log(request: Request, info_ids: str, query_db: Asy return ResponseUtil.success(msg=delete_login_log_result.message) -@logController.get( +@log_controller.get( '/logininfor/unlock/{user_name}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:unlock'))] ) @Log(title='账户解锁', business_type=BusinessType.OTHER) -async def unlock_system_user(request: Request, user_name: str, query_db: AsyncSession = Depends(get_db)): +async def unlock_system_user( + request: Request, + user_name: Annotated[str, Path(description='用户名称')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: unlock_user = UnlockUser(userName=user_name) unlock_user_result = await LoginLogService.unlock_user_services(request, unlock_user) logger.info(unlock_user_result.message) @@ -133,13 +147,13 @@ async def unlock_system_user(request: Request, user_name: str, query_db: AsyncSe return ResponseUtil.success(msg=unlock_user_result.message) -@logController.post('/logininfor/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:export'))]) +@log_controller.post('/logininfor/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:export'))]) @Log(title='登录日志', business_type=BusinessType.EXPORT) async def export_system_login_log_list( request: Request, - login_log_page_query: LoginLogPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + login_log_page_query: Annotated[LoginLogPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 login_log_query_result = await LoginLogService.get_login_log_list_services( query_db, login_log_page_query, is_page=False diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 1a3c198..0accf07 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -1,35 +1,35 @@ -import jwt import uuid from datetime import datetime, timedelta -from fastapi import APIRouter, Depends, Request +from typing import Annotated, Optional + +import jwt +from fastapi import APIRouter, Depends, Request, Response from sqlalchemy.ext.asyncio import AsyncSession -from typing import Optional + from config.enums import BusinessType, RedisInitKeyConfig from config.env import AppConfig, JwtConfig from config.get_db import get_db from module_admin.annotation.log_annotation import Log from module_admin.entity.vo.common_vo import CrudResponseModel -from module_admin.entity.vo.login_vo import UserLogin, UserRegister, Token +from module_admin.entity.vo.login_vo import Token, UserLogin, UserRegister from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel from module_admin.service.login_service import CustomOAuth2PasswordRequestForm, LoginService, oauth2_scheme from module_admin.service.user_service import UserService from utils.log_util import logger from utils.response_util import ResponseUtil - -loginController = APIRouter() +login_controller = APIRouter() -@loginController.post('/login', response_model=Token) +@login_controller.post('/login', response_model=Token) @Log(title='用户登录', business_type=BusinessType.OTHER, log_type='login') async def login( - request: Request, form_data: CustomOAuth2PasswordRequestForm = Depends(), query_db: AsyncSession = Depends(get_db) -): + request: Request, + form_data: Annotated[CustomOAuth2PasswordRequestForm, Depends()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: captcha_enabled = ( - True - if await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') - == 'true' - else False + await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true' ) user = UserLogin( userName=form_data.username, @@ -77,36 +77,40 @@ async def login( return ResponseUtil.success(msg='登录成功', dict_content={'token': access_token}) -@loginController.get('/getInfo', response_model=CurrentUserModel) +@login_controller.get('/getInfo', response_model=CurrentUserModel) async def get_login_user_info( - request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user) -): + request: Request, current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)] +) -> Response: logger.info('获取成功') return ResponseUtil.success(model_content=current_user) -@loginController.get('/getRouters') +@login_controller.get('/getRouters') async def get_login_user_routers( request: Request, - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - query_db: AsyncSession = Depends(get_db), -): + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: logger.info('获取成功') user_routers = await LoginService.get_current_user_routers(current_user.user.user_id, query_db) return ResponseUtil.success(data=user_routers) -@loginController.post('/register', response_model=CrudResponseModel) -async def register_user(request: Request, user_register: UserRegister, query_db: AsyncSession = Depends(get_db)): +@login_controller.post('/register', response_model=CrudResponseModel) +async def register_user( + request: Request, + user_register: UserRegister, + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: user_register_result = await LoginService.register_user_services(request, query_db, user_register) logger.info(user_register_result.message) return ResponseUtil.success(data=user_register_result, msg=user_register_result.message) -# @loginController.post("/getSmsCode", response_model=SmsCode) +# @login_controller.post("/getSmsCode", response_model=SmsCode) # async def get_sms_code(request: Request, user: ResetUserModel, query_db: AsyncSession = Depends(get_db)): # try: # sms_result = await LoginService.get_sms_code_services(request, query_db, user) @@ -121,7 +125,7 @@ async def register_user(request: Request, user_register: UserRegister, query_db: # return ResponseUtil.error(msg=str(e)) # # -# @loginController.post("/forgetPwd", response_model=CrudResponseModel) +# @login_controller.post("/forgetPwd", response_model=CrudResponseModel) # async def forget_user_pwd(request: Request, forget_user: ResetUserModel, query_db: AsyncSession = Depends(get_db)): # try: # forget_user_result = await LoginService.forget_user_services(request, query_db, forget_user) @@ -136,8 +140,8 @@ async def register_user(request: Request, user_register: UserRegister, query_db: # return ResponseUtil.error(msg=str(e)) -@loginController.post('/logout') -async def logout(request: Request, token: Optional[str] = Depends(oauth2_scheme)): +@login_controller.post('/logout') +async def logout(request: Request, token: Annotated[Optional[str], Depends(oauth2_scheme)]) -> Response: payload = jwt.decode( token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm], options={'verify_exp': False} ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index 0e3124e..4cf4d76 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -1,8 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -14,59 +16,58 @@ from module_admin.service.menu_service import MenuService from utils.log_util import logger from utils.response_util import ResponseUtil - -menuController = APIRouter(prefix='/system/menu', dependencies=[Depends(LoginService.get_current_user)]) +menu_controller = APIRouter(prefix='/system/menu', dependencies=[Depends(LoginService.get_current_user)]) -@menuController.get('/treeselect') +@menu_controller.get('/treeselect') async def get_system_menu_tree( request: Request, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: menu_query_result = await MenuService.get_menu_tree_services(query_db, current_user) logger.info('获取成功') return ResponseUtil.success(data=menu_query_result) -@menuController.get('/roleMenuTreeselect/{role_id}') +@menu_controller.get('/roleMenuTreeselect/{role_id}') async def get_system_role_menu_tree( request: Request, - role_id: int, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + role_id: Annotated[int, Path(description='角色ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: role_menu_query_result = await MenuService.get_role_menu_tree_services(query_db, role_id, current_user) logger.info('获取成功') return ResponseUtil.success(model_content=role_menu_query_result) -@menuController.get( - '/list', response_model=List[MenuModel], dependencies=[Depends(CheckUserInterfaceAuth('system:menu:list'))] +@menu_controller.get( + '/list', response_model=list[MenuModel], dependencies=[Depends(CheckUserInterfaceAuth('system:menu:list'))] ) async def get_system_menu_list( request: Request, - menu_query: MenuQueryModel = Depends(MenuQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + menu_query: Annotated[MenuQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: menu_query_result = await MenuService.get_menu_list_services(query_db, menu_query, current_user) logger.info('获取成功') return ResponseUtil.success(data=menu_query_result) -@menuController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:add'))]) +@menu_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:add'))]) @ValidateFields(validate_model='add_menu') @Log(title='菜单管理', business_type=BusinessType.INSERT) async def add_system_menu( request: Request, add_menu: MenuModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_menu.create_by = current_user.user.user_name add_menu.create_time = datetime.now() add_menu.update_by = current_user.user.user_name @@ -77,15 +78,15 @@ async def add_system_menu( return ResponseUtil.success(msg=add_menu_result.message) -@menuController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:edit'))]) +@menu_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:edit'))]) @ValidateFields(validate_model='edit_menu') @Log(title='菜单管理', business_type=BusinessType.UPDATE) async def edit_system_menu( request: Request, edit_menu: MenuModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_menu.update_by = current_user.user.user_name edit_menu.update_time = datetime.now() edit_menu_result = await MenuService.edit_menu_services(query_db, edit_menu) @@ -94,9 +95,13 @@ async def edit_system_menu( return ResponseUtil.success(msg=edit_menu_result.message) -@menuController.delete('/{menu_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:remove'))]) +@menu_controller.delete('/{menu_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:remove'))]) @Log(title='菜单管理', business_type=BusinessType.DELETE) -async def delete_system_menu(request: Request, menu_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_menu( + request: Request, + menu_ids: Annotated[str, Path(description='需要删除的菜单ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_menu = DeleteMenuModel(menuIds=menu_ids) delete_menu_result = await MenuService.delete_menu_services(query_db, delete_menu) logger.info(delete_menu_result.message) @@ -104,10 +109,14 @@ async def delete_system_menu(request: Request, menu_ids: str, query_db: AsyncSes return ResponseUtil.success(msg=delete_menu_result.message) -@menuController.get( +@menu_controller.get( '/{menu_id}', response_model=MenuModel, dependencies=[Depends(CheckUserInterfaceAuth('system:menu:query'))] ) -async def query_detail_system_menu(request: Request, menu_id: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_menu( + request: Request, + menu_id: Annotated[int, Path(description='菜单ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: menu_detail_result = await MenuService.menu_detail_services(query_db, menu_id) logger.info(f'获取menu_id为{menu_id}的信息成功') diff --git a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py index e1e4aa1..9a01737 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py @@ -1,7 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -14,18 +17,17 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -noticeController = APIRouter(prefix='/system/notice', dependencies=[Depends(LoginService.get_current_user)]) +notice_controller = APIRouter(prefix='/system/notice', dependencies=[Depends(LoginService.get_current_user)]) -@noticeController.get( +@notice_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:notice:list'))] ) async def get_system_notice_list( request: Request, - notice_page_query: NoticePageQueryModel = Depends(NoticePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + notice_page_query: Annotated[NoticePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 notice_page_query_result = await NoticeService.get_notice_list_services(query_db, notice_page_query, is_page=True) logger.info('获取成功') @@ -33,15 +35,15 @@ async def get_system_notice_list( return ResponseUtil.success(model_content=notice_page_query_result) -@noticeController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:add'))]) +@notice_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:add'))]) @ValidateFields(validate_model='add_notice') @Log(title='通知公告', business_type=BusinessType.INSERT) async def add_system_notice( request: Request, add_notice: NoticeModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_notice.create_by = current_user.user.user_name add_notice.create_time = datetime.now() add_notice.update_by = current_user.user.user_name @@ -52,15 +54,15 @@ async def add_system_notice( return ResponseUtil.success(msg=add_notice_result.message) -@noticeController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:edit'))]) +@notice_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:edit'))]) @ValidateFields(validate_model='edit_notice') @Log(title='通知公告', business_type=BusinessType.UPDATE) async def edit_system_notice( request: Request, edit_notice: NoticeModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_notice.update_by = current_user.user.user_name edit_notice.update_time = datetime.now() edit_notice_result = await NoticeService.edit_notice_services(query_db, edit_notice) @@ -69,9 +71,13 @@ async def edit_system_notice( return ResponseUtil.success(msg=edit_notice_result.message) -@noticeController.delete('/{notice_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:remove'))]) +@notice_controller.delete('/{notice_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:remove'))]) @Log(title='通知公告', business_type=BusinessType.DELETE) -async def delete_system_notice(request: Request, notice_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_notice( + request: Request, + notice_ids: Annotated[str, Path(description='需要删除的公告ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_notice = DeleteNoticeModel(noticeIds=notice_ids) delete_notice_result = await NoticeService.delete_notice_services(query_db, delete_notice) logger.info(delete_notice_result.message) @@ -79,10 +85,14 @@ async def delete_system_notice(request: Request, notice_ids: str, query_db: Asyn return ResponseUtil.success(msg=delete_notice_result.message) -@noticeController.get( +@notice_controller.get( '/{notice_id}', response_model=NoticeModel, dependencies=[Depends(CheckUserInterfaceAuth('system:notice:query'))] ) -async def query_detail_system_post(request: Request, notice_id: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_post( + request: Request, + notice_id: Annotated[int, Path(description='公告ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: notice_detail_result = await NoticeService.notice_detail_services(query_db, notice_id) logger.info(f'获取notice_id为{notice_id}的信息成功') diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index bf65c8f..70c731c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -1,5 +1,8 @@ -from fastapi import APIRouter, Depends, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -11,16 +14,16 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -onlineController = APIRouter(prefix='/monitor/online', dependencies=[Depends(LoginService.get_current_user)]) +online_controller = APIRouter(prefix='/monitor/online', dependencies=[Depends(LoginService.get_current_user)]) -@onlineController.get( +@online_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:online:list'))] ) async def get_monitor_online_list( - request: Request, online_page_query: OnlineQueryModel = Depends(OnlineQueryModel.as_query) -): + request: Request, + online_page_query: Annotated[OnlineQueryModel, Query()], +) -> Response: # 获取全量数据 online_query_result = await OnlineService.get_online_list_services(request, online_page_query) logger.info('获取成功') @@ -30,9 +33,13 @@ async def get_monitor_online_list( ) -@onlineController.delete('/{token_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:online:forceLogout'))]) +@online_controller.delete('/{token_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:online:forceLogout'))]) @Log(title='在线用户', business_type=BusinessType.FORCE) -async def delete_monitor_online(request: Request, token_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_monitor_online( + request: Request, + token_ids: Annotated[str, Path(description='需要强退的会话编号')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_online = DeleteOnlineModel(tokenIds=token_ids) delete_online_result = await OnlineService.delete_online_services(request, delete_online) logger.info(delete_online_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controler.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py similarity index 67% rename from ruoyi-fastapi-backend/module_admin/controller/post_controler.py rename to ruoyi-fastapi-backend/module_admin/controller/post_controller.py index e9c69c4..475849d 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controler.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -1,32 +1,34 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log from module_admin.aspect.interface_auth import CheckUserInterfaceAuth -from module_admin.service.login_service import LoginService -from module_admin.service.post_service import PostService from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel +from module_admin.service.login_service import LoginService +from module_admin.service.post_service import PostService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -postController = APIRouter(prefix='/system/post', dependencies=[Depends(LoginService.get_current_user)]) +post_controller = APIRouter(prefix='/system/post', dependencies=[Depends(LoginService.get_current_user)]) -@postController.get( +@post_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:post:list'))] ) async def get_system_post_list( request: Request, - post_page_query: PostPageQueryModel = Depends(PostPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + post_page_query: Annotated[PostPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 post_page_query_result = await PostService.get_post_list_services(query_db, post_page_query, is_page=True) logger.info('获取成功') @@ -34,15 +36,15 @@ async def get_system_post_list( return ResponseUtil.success(model_content=post_page_query_result) -@postController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:post:add'))]) +@post_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:post:add'))]) @ValidateFields(validate_model='add_post') @Log(title='岗位管理', business_type=BusinessType.INSERT) async def add_system_post( request: Request, add_post: PostModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_post.create_by = current_user.user.user_name add_post.create_time = datetime.now() add_post.update_by = current_user.user.user_name @@ -53,15 +55,15 @@ async def add_system_post( return ResponseUtil.success(msg=add_post_result.message) -@postController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:post:edit'))]) +@post_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:post:edit'))]) @ValidateFields(validate_model='edit_post') @Log(title='岗位管理', business_type=BusinessType.UPDATE) async def edit_system_post( request: Request, edit_post: PostModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_post.update_by = current_user.user.user_name edit_post.update_time = datetime.now() edit_post_result = await PostService.edit_post_services(query_db, edit_post) @@ -70,9 +72,13 @@ async def edit_system_post( return ResponseUtil.success(msg=edit_post_result.message) -@postController.delete('/{post_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:post:remove'))]) +@post_controller.delete('/{post_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:post:remove'))]) @Log(title='岗位管理', business_type=BusinessType.DELETE) -async def delete_system_post(request: Request, post_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_system_post( + request: Request, + post_ids: Annotated[str, Path(description='需要删除的岗位ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_post = DeletePostModel(postIds=post_ids) delete_post_result = await PostService.delete_post_services(query_db, delete_post) logger.info(delete_post_result.message) @@ -80,23 +86,27 @@ async def delete_system_post(request: Request, post_ids: str, query_db: AsyncSes return ResponseUtil.success(msg=delete_post_result.message) -@postController.get( +@post_controller.get( '/{post_id}', response_model=PostModel, dependencies=[Depends(CheckUserInterfaceAuth('system:post:query'))] ) -async def query_detail_system_post(request: Request, post_id: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_system_post( + request: Request, + post_id: Annotated[int, Path(description='岗位ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: post_detail_result = await PostService.post_detail_services(query_db, post_id) logger.info(f'获取post_id为{post_id}的信息成功') return ResponseUtil.success(data=post_detail_result) -@postController.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:post:export'))]) +@post_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:post:export'))]) @Log(title='岗位管理', business_type=BusinessType.EXPORT) async def export_system_post_list( request: Request, - post_page_query: PostPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + post_page_query: Annotated[PostPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 post_query_result = await PostService.get_post_list_services(query_db, post_page_query, is_page=False) post_export_result = await PostService.export_post_list_services(post_query_result) diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index d4ab531..5e52133 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -1,7 +1,10 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -19,18 +22,17 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -roleController = APIRouter(prefix='/system/role', dependencies=[Depends(LoginService.get_current_user)]) +role_controller = APIRouter(prefix='/system/role', dependencies=[Depends(LoginService.get_current_user)]) -@roleController.get('/deptTree/{role_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))]) +@role_controller.get('/deptTree/{role_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))]) async def get_system_role_dept_tree( request: Request, - role_id: int, - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): - dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(**{}), data_scope_sql) + role_id: Annotated[int, Path(description='角色ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: + dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql) role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id) role_dept_query_result.depts = dept_query_result logger.info('获取成功') @@ -38,15 +40,15 @@ async def get_system_role_dept_tree( return ResponseUtil.success(model_content=role_dept_query_result) -@roleController.get( +@role_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))] ) async def get_system_role_list( request: Request, - role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + role_page_query: Annotated[RolePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: role_page_query_result = await RoleService.get_role_list_services( query_db, role_page_query, data_scope_sql, is_page=True ) @@ -55,15 +57,15 @@ async def get_system_role_list( return ResponseUtil.success(model_content=role_page_query_result) -@roleController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:role:add'))]) +@role_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:role:add'))]) @ValidateFields(validate_model='add_role') @Log(title='角色管理', business_type=BusinessType.INSERT) async def add_system_role( request: Request, add_role: AddRoleModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: add_role.create_by = current_user.user.user_name add_role.create_time = datetime.now() add_role.update_by = current_user.user.user_name @@ -74,16 +76,16 @@ async def add_system_role( return ResponseUtil.success(msg=add_role_result.message) -@roleController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @ValidateFields(validate_model='edit_role') @Log(title='角色管理', business_type=BusinessType.UPDATE) async def edit_system_role( request: Request, edit_role: AddRoleModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: await RoleService.check_role_allowed_services(edit_role) if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(edit_role.role_id), data_scope_sql) @@ -95,15 +97,15 @@ async def edit_system_role( return ResponseUtil.success(msg=edit_role_result.message) -@roleController.put('/dataScope', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put('/dataScope', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @Log(title='角色管理', business_type=BusinessType.GRANT) async def edit_system_role_datascope( request: Request, role_data_scope: AddRoleModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: await RoleService.check_role_allowed_services(role_data_scope) if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(role_data_scope.role_id), data_scope_sql) @@ -121,15 +123,15 @@ async def edit_system_role_datascope( return ResponseUtil.success(msg=role_data_scope_result.message) -@roleController.delete('/{role_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:role:remove'))]) +@role_controller.delete('/{role_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:role:remove'))]) @Log(title='角色管理', business_type=BusinessType.DELETE) async def delete_system_role( request: Request, - role_ids: str, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + role_ids: Annotated[str, Path(description='需要删除的角色ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: role_id_list = role_ids.split(',') if role_ids else [] if role_id_list: for role_id in role_id_list: @@ -143,16 +145,16 @@ async def delete_system_role( return ResponseUtil.success(msg=delete_role_result.message) -@roleController.get( +@role_controller.get( '/{role_id}', response_model=RoleModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))] ) async def query_detail_system_role( request: Request, - role_id: int, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + role_id: Annotated[int, Path(description='角色ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(role_id), data_scope_sql) role_detail_result = await RoleService.role_detail_services(query_db, role_id) @@ -161,14 +163,14 @@ async def query_detail_system_role( return ResponseUtil.success(data=role_detail_result.model_dump(by_alias=True)) -@roleController.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:role:export'))]) +@role_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:role:export'))]) @Log(title='角色管理', business_type=BusinessType.EXPORT) async def export_system_role_list( request: Request, - role_page_query: RolePageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + role_page_query: Annotated[RolePageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: # 获取全量数据 role_query_result = await RoleService.get_role_list_services( query_db, role_page_query, data_scope_sql, is_page=False @@ -179,15 +181,15 @@ async def export_system_role_list( return ResponseUtil.streaming(data=bytes2file_response(role_export_result)) -@roleController.put('/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put('/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @Log(title='角色管理', business_type=BusinessType.UPDATE) async def reset_system_role_status( request: Request, change_role: AddRoleModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: await RoleService.check_role_allowed_services(change_role) if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(change_role.role_id), data_scope_sql) @@ -204,17 +206,17 @@ async def reset_system_role_status( return ResponseUtil.success(msg=edit_role_result.message) -@roleController.get( +@role_controller.get( '/authUser/allocatedList', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))], ) async def get_system_allocated_user_list( request: Request, - user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + user_role: Annotated[UserRolePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services( query_db, user_role, data_scope_sql, is_page=True ) @@ -223,17 +225,17 @@ async def get_system_allocated_user_list( return ResponseUtil.success(model_content=role_user_allocated_page_query_result) -@roleController.get( +@role_controller.get( '/authUser/unallocatedList', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))], ) async def get_system_unallocated_user_list( request: Request, - user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + user_role: Annotated[UserRolePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services( query_db, user_role, data_scope_sql, is_page=True ) @@ -242,15 +244,15 @@ async def get_system_unallocated_user_list( return ResponseUtil.success(model_content=role_user_unallocated_page_query_result) -@roleController.put('/authUser/selectAll', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put('/authUser/selectAll', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @Log(title='角色管理', business_type=BusinessType.GRANT) async def add_system_role_user( request: Request, - add_role_user: CrudUserRoleModel = Depends(CrudUserRoleModel.as_query), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + add_role_user: Annotated[CrudUserRoleModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(add_role_user.role_id), data_scope_sql) add_role_user_result = await UserService.add_user_role_services(query_db, add_role_user) @@ -259,24 +261,26 @@ async def add_system_role_user( return ResponseUtil.success(msg=add_role_user_result.message) -@roleController.put('/authUser/cancel', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put('/authUser/cancel', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @Log(title='角色管理', business_type=BusinessType.GRANT) async def cancel_system_role_user( - request: Request, cancel_user_role: CrudUserRoleModel, query_db: AsyncSession = Depends(get_db) -): + request: Request, + cancel_user_role: CrudUserRoleModel, + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: cancel_user_role_result = await UserService.delete_user_role_services(query_db, cancel_user_role) logger.info(cancel_user_role_result.message) return ResponseUtil.success(msg=cancel_user_role_result.message) -@roleController.put('/authUser/cancelAll', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put('/authUser/cancelAll', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) @Log(title='角色管理', business_type=BusinessType.GRANT) async def batch_cancel_system_role_user( request: Request, - batch_cancel_user_role: CrudUserRoleModel = Depends(CrudUserRoleModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + batch_cancel_user_role: Annotated[CrudUserRoleModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: batch_cancel_user_role_result = await UserService.delete_user_role_services(query_db, batch_cancel_user_role) logger.info(batch_cancel_user_role_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index f63fdf8..2258e83 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -1,19 +1,19 @@ -from fastapi import APIRouter, Depends, Request +from fastapi import APIRouter, Depends, Request, Response + from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.server_vo import ServerMonitorModel from module_admin.service.login_service import LoginService from module_admin.service.server_service import ServerService -from utils.response_util import ResponseUtil from utils.log_util import logger +from utils.response_util import ResponseUtil + +server_controller = APIRouter(prefix='/monitor/server', dependencies=[Depends(LoginService.get_current_user)]) -serverController = APIRouter(prefix='/monitor/server', dependencies=[Depends(LoginService.get_current_user)]) - - -@serverController.get( +@server_controller.get( '', response_model=ServerMonitorModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:server:list'))] ) -async def get_monitor_server_info(request: Request): +async def get_monitor_server_info(request: Request) -> Response: # 获取全量数据 server_info_query_result = await ServerService.get_server_monitor_info() logger.info('获取成功') diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index 91d6611..c36604b 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -1,12 +1,15 @@ import os from datetime import datetime -from fastapi import APIRouter, Depends, File, Form, Query, Request, UploadFile -from sqlalchemy.ext.asyncio import AsyncSession -from typing import Literal, Optional, Union +from typing import Annotated, Literal, Optional, Union + +import aiofiles +from fastapi import APIRouter, Depends, File, Form, Path, Query, Request, Response, UploadFile from pydantic_validation_decorator import ValidateFields -from config.get_db import get_db +from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.env import UploadConfig +from config.get_db import get_db from module_admin.annotation.log_annotation import Log from module_admin.aspect.data_scope import GetDataScope from module_admin.aspect.interface_auth import CheckUserInterfaceAuth @@ -27,10 +30,10 @@ from module_admin.entity.vo.user_vo import ( UserRoleQueryModel, UserRoleResponseModel, ) -from module_admin.service.login_service import LoginService -from module_admin.service.user_service import UserService -from module_admin.service.role_service import RoleService from module_admin.service.dept_service import DeptService +from module_admin.service.login_service import LoginService +from module_admin.service.role_service import RoleService +from module_admin.service.user_service import UserService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel @@ -38,29 +41,30 @@ from utils.pwd_util import PwdUtil from utils.response_util import ResponseUtil from utils.upload_util import UploadUtil - -userController = APIRouter(prefix='/system/user', dependencies=[Depends(LoginService.get_current_user)]) +user_controller = APIRouter(prefix='/system/user', dependencies=[Depends(LoginService.get_current_user)]) -@userController.get('/deptTree', dependencies=[Depends(CheckUserInterfaceAuth('system:user:list'))]) +@user_controller.get('/deptTree', dependencies=[Depends(CheckUserInterfaceAuth('system:user:list'))]) async def get_system_dept_tree( - request: Request, query_db: AsyncSession = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('SysDept')) -): - dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(**{}), data_scope_sql) + request: Request, + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: + dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql) logger.info('获取成功') return ResponseUtil.success(data=dept_query_result) -@userController.get( +@user_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:list'))] ) async def get_system_user_list( request: Request, - user_page_query: UserPageQueryModel = Depends(UserPageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + user_page_query: Annotated[UserPageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: # 获取分页数据 user_page_query_result = await UserService.get_user_list_services( query_db, user_page_query, data_scope_sql, is_page=True @@ -70,17 +74,17 @@ async def get_system_user_list( return ResponseUtil.success(model_content=user_page_query_result) -@userController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:user:add'))]) +@user_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:user:add'))]) @ValidateFields(validate_model='add_user') @Log(title='用户管理', business_type=BusinessType.INSERT) async def add_system_user( request: Request, add_user: AddUserModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - dept_data_scope_sql: str = Depends(GetDataScope('SysDept')), - role_data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + dept_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + role_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: if not current_user.user.admin: await DeptService.check_dept_data_scope_services(query_db, add_user.dept_id, dept_data_scope_sql) await RoleService.check_role_data_scope_services( @@ -97,18 +101,18 @@ async def add_system_user( return ResponseUtil.success(msg=add_user_result.message) -@userController.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))]) +@user_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))]) @ValidateFields(validate_model='edit_user') @Log(title='用户管理', business_type=BusinessType.UPDATE) async def edit_system_user( request: Request, edit_user: EditUserModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - user_data_scope_sql: str = Depends(GetDataScope('SysUser')), - dept_data_scope_sql: str = Depends(GetDataScope('SysDept')), - role_data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + user_data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + dept_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + role_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: await UserService.check_user_allowed_services(edit_user) if not current_user.user.admin: await UserService.check_user_data_scope_services(query_db, edit_user.user_id, user_data_scope_sql) @@ -124,15 +128,15 @@ async def edit_system_user( return ResponseUtil.success(msg=edit_user_result.message) -@userController.delete('/{user_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:user:remove'))]) +@user_controller.delete('/{user_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:user:remove'))]) @Log(title='用户管理', business_type=BusinessType.DELETE) async def delete_system_user( request: Request, - user_ids: str, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + user_ids: Annotated[str, Path(description='需要删除的用户ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: user_id_list = user_ids.split(',') if user_ids else [] if user_id_list: if current_user.user.user_id in list(map(int, user_id_list)): @@ -150,15 +154,15 @@ async def delete_system_user( return ResponseUtil.success(msg=delete_user_result.message) -@userController.put('/resetPwd', dependencies=[Depends(CheckUserInterfaceAuth('system:user:resetPwd'))]) +@user_controller.put('/resetPwd', dependencies=[Depends(CheckUserInterfaceAuth('system:user:resetPwd'))]) @Log(title='用户管理', business_type=BusinessType.UPDATE) async def reset_system_user_pwd( request: Request, reset_user: EditUserModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: await UserService.check_user_allowed_services(reset_user) if not current_user.user.admin: await UserService.check_user_data_scope_services(query_db, reset_user.user_id, data_scope_sql) @@ -176,15 +180,15 @@ async def reset_system_user_pwd( return ResponseUtil.success(msg=edit_user_result.message) -@userController.put('/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))]) +@user_controller.put('/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))]) @Log(title='用户管理', business_type=BusinessType.UPDATE) async def change_system_user_status( request: Request, change_user: EditUserModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: await UserService.check_user_allowed_services(change_user) if not current_user.user.admin: await UserService.check_user_data_scope_services(query_db, change_user.user_id, data_scope_sql) @@ -201,31 +205,31 @@ async def change_system_user_status( return ResponseUtil.success(msg=edit_user_result.message) -@userController.get('/profile', response_model=UserProfileModel) +@user_controller.get('/profile', response_model=UserProfileModel) async def query_detail_system_user_profile( request: Request, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: profile_user_result = await UserService.user_profile_services(query_db, current_user.user.user_id) logger.info(f'获取user_id为{current_user.user.user_id}的信息成功') return ResponseUtil.success(model_content=profile_user_result) -@userController.get( +@user_controller.get( '/{user_id}', response_model=UserDetailModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:query'))] ) -@userController.get( +@user_controller.get( '/', response_model=UserDetailModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:query'))] ) async def query_detail_system_user( request: Request, + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], user_id: Optional[Union[int, Literal['']]] = '', - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): +) -> Response: if user_id and not current_user.user.admin: await UserService.check_user_data_scope_services(query_db, user_id, data_scope_sql) detail_user_result = await UserService.user_detail_services(query_db, user_id) @@ -234,14 +238,14 @@ async def query_detail_system_user( return ResponseUtil.success(model_content=detail_user_result) -@userController.post('/profile/avatar') +@user_controller.post('/profile/avatar') @Log(title='个人信息', business_type=BusinessType.UPDATE) async def change_system_user_profile_avatar( request: Request, - avatarfile: bytes = File(), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + avatarfile: Annotated[bytes, File()], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: if avatarfile: relative_path = ( f'avatar/{datetime.now().strftime("%Y")}/{datetime.now().strftime("%m")}/{datetime.now().strftime("%d")}' @@ -253,8 +257,8 @@ async def change_system_user_profile_avatar( pass avatar_name = f'avatar_{datetime.now().strftime("%Y%m%d%H%M%S")}{UploadConfig.UPLOAD_MACHINE}{UploadUtil.generate_random_number()}.png' avatar_path = os.path.join(dir_path, avatar_name) - with open(avatar_path, 'wb') as f: - f.write(avatarfile) + async with aiofiles.open(avatar_path, 'wb') as f: + await f.write(avatarfile) edit_user = EditUserModel( userId=current_user.user.user_id, avatar=f'{UploadConfig.UPLOAD_PREFIX}/{relative_path}/{avatar_name}', @@ -269,14 +273,14 @@ async def change_system_user_profile_avatar( return ResponseUtil.failure(msg='上传图片异常,请联系管理员') -@userController.put('/profile') +@user_controller.put('/profile') @Log(title='个人信息', business_type=BusinessType.UPDATE) async def change_system_user_profile_info( request: Request, user_info: UserInfoModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_user = EditUserModel( **user_info.model_dump(exclude_unset=True, by_alias=True, exclude={'role_ids', 'post_ids'}), userId=current_user.user.user_id, @@ -293,14 +297,14 @@ async def change_system_user_profile_info( return ResponseUtil.success(msg=edit_user_result.message) -@userController.put('/profile/updatePwd') +@user_controller.put('/profile/updatePwd') @Log(title='个人信息', business_type=BusinessType.UPDATE) async def reset_system_user_password( request: Request, reset_password: ResetPasswordModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: reset_user = ResetUserModel( userId=current_user.user.user_id, oldPassword=reset_password.old_password, @@ -315,17 +319,17 @@ async def reset_system_user_password( return ResponseUtil.success(msg=reset_user_result.message) -@userController.post('/importData', dependencies=[Depends(CheckUserInterfaceAuth('system:user:import'))]) +@user_controller.post('/importData', dependencies=[Depends(CheckUserInterfaceAuth('system:user:import'))]) @Log(title='用户管理', business_type=BusinessType.IMPORT) async def batch_import_system_user( request: Request, - file: UploadFile = File(...), - update_support: bool = Query(alias='updateSupport'), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - user_data_scope_sql: str = Depends(GetDataScope('SysUser')), - dept_data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + file: Annotated[UploadFile, File(...)], + update_support: Annotated[bool, Query(alias='updateSupport')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + user_data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + dept_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: batch_import_result = await UserService.batch_import_user_services( request, query_db, file, update_support, current_user, user_data_scope_sql, dept_data_scope_sql ) @@ -334,22 +338,22 @@ async def batch_import_system_user( return ResponseUtil.success(msg=batch_import_result.message) -@userController.post('/importTemplate', dependencies=[Depends(CheckUserInterfaceAuth('system:user:import'))]) -async def export_system_user_template(request: Request, query_db: AsyncSession = Depends(get_db)): +@user_controller.post('/importTemplate', dependencies=[Depends(CheckUserInterfaceAuth('system:user:import'))]) +async def export_system_user_template(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: user_import_template_result = await UserService.get_user_import_template_services() logger.info('获取成功') return ResponseUtil.streaming(data=bytes2file_response(user_import_template_result)) -@userController.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:user:export'))]) +@user_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:user:export'))]) @Log(title='用户管理', business_type=BusinessType.EXPORT) async def export_system_user_list( request: Request, - user_page_query: UserPageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), - data_scope_sql: str = Depends(GetDataScope('SysUser')), -): + user_page_query: Annotated[UserPageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], + data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], +) -> Response: # 获取全量数据 user_query_result = await UserService.get_user_list_services( query_db, user_page_query, data_scope_sql, is_page=False @@ -360,12 +364,16 @@ async def export_system_user_list( return ResponseUtil.streaming(data=bytes2file_response(user_export_result)) -@userController.get( +@user_controller.get( '/authRole/{user_id}', response_model=UserRoleResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:query'))], ) -async def get_system_allocated_role_list(request: Request, user_id: int, query_db: AsyncSession = Depends(get_db)): +async def get_system_allocated_role_list( + request: Request, + user_id: Annotated[int, Path(description='用户ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: user_role_query = UserRoleQueryModel(userId=user_id) user_role_allocated_query_result = await UserService.get_user_role_allocated_list_services( query_db, user_role_query @@ -375,7 +383,7 @@ async def get_system_allocated_role_list(request: Request, user_id: int, query_d return ResponseUtil.success(model_content=user_role_allocated_query_result) -@userController.put( +@user_controller.put( '/authRole', response_model=UserRoleResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))], @@ -383,13 +391,13 @@ async def get_system_allocated_role_list(request: Request, user_id: int, query_d @Log(title='用户管理', business_type=BusinessType.GRANT) async def update_system_role_user( request: Request, - user_id: int = Query(alias='userId'), - role_ids: str = Query(alias='roleIds'), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), - user_data_scope_sql: str = Depends(GetDataScope('SysUser')), - role_data_scope_sql: str = Depends(GetDataScope('SysDept')), -): + user_id: Annotated[int, Query(alias='userId')], + role_ids: Annotated[str, Query(alias='roleIds')], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + user_data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + role_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], +) -> Response: if not current_user.user.admin: await UserService.check_user_data_scope_services(query_db, user_id, user_data_scope_sql) await RoleService.check_role_data_scope_services(query_db, role_ids, role_data_scope_sql) diff --git a/ruoyi-fastapi-backend/module_admin/dao/config_dao.py b/ruoyi-fastapi-backend/module_admin/dao/config_dao.py index 4f34a2f..0e63ed3 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/config_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/config_dao.py @@ -1,9 +1,12 @@ from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.config_do import SysConfig from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class ConfigDao: @@ -12,7 +15,7 @@ class ConfigDao: """ @classmethod - async def get_config_detail_by_id(cls, db: AsyncSession, config_id: int): + async def get_config_detail_by_id(cls, db: AsyncSession, config_id: int) -> Union[SysConfig, None]: """ 根据参数配置id获取参数配置详细信息 @@ -25,7 +28,7 @@ class ConfigDao: return config_info @classmethod - async def get_config_detail_by_info(cls, db: AsyncSession, config: ConfigModel): + async def get_config_detail_by_info(cls, db: AsyncSession, config: ConfigModel) -> Union[SysConfig, None]: """ 根据参数配置参数获取参数配置信息 @@ -49,7 +52,9 @@ class ConfigDao: return config_info @classmethod - async def get_config_list(cls, db: AsyncSession, query_object: ConfigPageQueryModel, is_page: bool = False): + async def get_config_list( + cls, db: AsyncSession, query_object: ConfigPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取参数配置列表信息 @@ -74,12 +79,14 @@ class ConfigDao: .order_by(SysConfig.config_id) .distinct() ) - config_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + config_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return config_list @classmethod - async def add_config_dao(cls, db: AsyncSession, config: ConfigModel): + async def add_config_dao(cls, db: AsyncSession, config: ConfigModel) -> SysConfig: """ 新增参数配置数据库操作 @@ -94,7 +101,7 @@ class ConfigDao: return db_config @classmethod - async def edit_config_dao(cls, db: AsyncSession, config: dict): + async def edit_config_dao(cls, db: AsyncSession, config: dict) -> None: """ 编辑参数配置数据库操作 @@ -105,7 +112,7 @@ class ConfigDao: await db.execute(update(SysConfig), [config]) @classmethod - async def delete_config_dao(cls, db: AsyncSession, config: ConfigModel): + async def delete_config_dao(cls, db: AsyncSession, config: ConfigModel) -> None: """ 删除参数配置数据库操作 diff --git a/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py b/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py index f450210..8fc7581 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/dept_dao.py @@ -1,7 +1,10 @@ +from collections.abc import Sequence +from typing import Union + from sqlalchemy import bindparam, func, or_, select, update # noqa: F401 from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.util import immutabledict -from typing import List + from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.role_do import SysRoleDept # noqa: F401 from module_admin.entity.do.user_do import SysUser @@ -14,7 +17,7 @@ class DeptDao: """ @classmethod - async def get_dept_by_id(cls, db: AsyncSession, dept_id: int): + async def get_dept_by_id(cls, db: AsyncSession, dept_id: int) -> Union[SysDept, None]: """ 根据部门id获取在用部门信息 @@ -27,7 +30,7 @@ class DeptDao: return dept_info @classmethod - async def get_dept_detail_by_id(cls, db: AsyncSession, dept_id: int): + async def get_dept_detail_by_id(cls, db: AsyncSession, dept_id: int) -> Union[SysDept, None]: """ 根据部门id获取部门详细信息 @@ -44,7 +47,7 @@ class DeptDao: return dept_info @classmethod - async def get_dept_detail_by_info(cls, db: AsyncSession, dept: DeptModel): + async def get_dept_detail_by_info(cls, db: AsyncSession, dept: DeptModel) -> Union[SysDept, None]: """ 根据部门参数获取部门信息 @@ -68,7 +71,9 @@ class DeptDao: return dept_info @classmethod - async def get_dept_info_for_edit_option(cls, db: AsyncSession, dept_info: DeptModel, data_scope_sql: str): + async def get_dept_info_for_edit_option( + cls, db: AsyncSession, dept_info: DeptModel, data_scope_sql: str + ) -> Sequence[SysDept]: """ 获取部门编辑对应的在用部门列表信息 @@ -101,7 +106,7 @@ class DeptDao: return dept_result @classmethod - async def get_children_dept_dao(cls, db: AsyncSession, dept_id: int): + async def get_children_dept_dao(cls, db: AsyncSession, dept_id: int) -> Sequence[SysDept]: """ 根据部门id查询当前部门的子部门列表信息 @@ -116,7 +121,9 @@ class DeptDao: return dept_result @classmethod - async def get_dept_list_for_tree(cls, db: AsyncSession, dept_info: DeptModel, data_scope_sql: str): + async def get_dept_list_for_tree( + cls, db: AsyncSession, dept_info: DeptModel, data_scope_sql: str + ) -> Sequence[SysDept]: """ 获取所有在用部门列表信息 @@ -146,7 +153,7 @@ class DeptDao: return dept_result @classmethod - async def get_dept_list(cls, db: AsyncSession, page_object: DeptModel, data_scope_sql: str): + async def get_dept_list(cls, db: AsyncSession, page_object: DeptModel, data_scope_sql: str) -> Sequence[SysDept]: """ 根据查询参数获取部门列表信息 @@ -177,7 +184,7 @@ class DeptDao: return dept_result @classmethod - async def add_dept_dao(cls, db: AsyncSession, dept: DeptModel): + async def add_dept_dao(cls, db: AsyncSession, dept: DeptModel) -> SysDept: """ 新增部门数据库操作 @@ -192,7 +199,7 @@ class DeptDao: return db_dept @classmethod - async def edit_dept_dao(cls, db: AsyncSession, dept: dict): + async def edit_dept_dao(cls, db: AsyncSession, dept: dict) -> None: """ 编辑部门数据库操作 @@ -203,7 +210,7 @@ class DeptDao: await db.execute(update(SysDept), [dept]) @classmethod - async def update_dept_children_dao(cls, db: AsyncSession, update_dept: List): + async def update_dept_children_dao(cls, db: AsyncSession, update_dept: list) -> None: """ 更新子部门信息 @@ -225,7 +232,7 @@ class DeptDao: ) @classmethod - async def update_dept_status_normal_dao(cls, db: AsyncSession, dept_id_list: List): + async def update_dept_status_normal_dao(cls, db: AsyncSession, dept_id_list: list) -> None: """ 批量更新部门状态为正常 @@ -236,7 +243,7 @@ class DeptDao: await db.execute(update(SysDept).where(SysDept.dept_id.in_(dept_id_list)).values(status='0')) @classmethod - async def delete_dept_dao(cls, db: AsyncSession, dept: DeptModel): + async def delete_dept_dao(cls, db: AsyncSession, dept: DeptModel) -> None: """ 删除部门数据库操作 @@ -251,7 +258,7 @@ class DeptDao: ) @classmethod - async def count_normal_children_dept_dao(cls, db: AsyncSession, dept_id: int): + async def count_normal_children_dept_dao(cls, db: AsyncSession, dept_id: int) -> Union[int, None]: """ 根据部门id查询查询所有子部门(正常状态)的数量 @@ -270,7 +277,7 @@ class DeptDao: return normal_children_dept_count @classmethod - async def count_children_dept_dao(cls, db: AsyncSession, dept_id: int): + async def count_children_dept_dao(cls, db: AsyncSession, dept_id: int) -> Union[int, None]: """ 根据部门id查询查询所有子部门(所有状态)的数量 @@ -290,7 +297,7 @@ class DeptDao: return children_dept_count @classmethod - async def count_dept_user_dao(cls, db: AsyncSession, dept_id: int): + async def count_dept_user_dao(cls, db: AsyncSession, dept_id: int) -> Union[int, None]: """ 根据部门id查询查询部门下的用户数量 diff --git a/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py b/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py index c5a8ed5..eee5236 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py @@ -1,9 +1,13 @@ +from collections.abc import Sequence from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import and_, delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession -from module_admin.entity.do.dict_do import SysDictType, SysDictData + +from module_admin.entity.do.dict_do import SysDictData, SysDictType from module_admin.entity.vo.dict_vo import DictDataModel, DictDataPageQueryModel, DictTypeModel, DictTypePageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil from utils.time_format_util import list_format_datetime @@ -13,7 +17,7 @@ class DictTypeDao: """ @classmethod - async def get_dict_type_detail_by_id(cls, db: AsyncSession, dict_id: int): + async def get_dict_type_detail_by_id(cls, db: AsyncSession, dict_id: int) -> Union[SysDictType, None]: """ 根据字典类型id获取字典类型详细信息 @@ -26,7 +30,7 @@ class DictTypeDao: return dict_type_info @classmethod - async def get_dict_type_detail_by_info(cls, db: AsyncSession, dict_type: DictTypeModel): + async def get_dict_type_detail_by_info(cls, db: AsyncSession, dict_type: DictTypeModel) -> Union[SysDictType, None]: """ 根据字典类型参数获取字典类型信息 @@ -50,7 +54,7 @@ class DictTypeDao: return dict_type_info @classmethod - async def get_all_dict_type(cls, db: AsyncSession): + async def get_all_dict_type(cls, db: AsyncSession) -> list[Any]: """ 获取所有的字典类型信息 @@ -62,7 +66,9 @@ class DictTypeDao: return list_format_datetime(dict_type_info) @classmethod - async def get_dict_type_list(cls, db: AsyncSession, query_object: DictTypePageQueryModel, is_page: bool = False): + async def get_dict_type_list( + cls, db: AsyncSession, query_object: DictTypePageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取字典类型列表信息 @@ -87,12 +93,14 @@ class DictTypeDao: .order_by(SysDictType.dict_id) .distinct() ) - dict_type_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + dict_type_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return dict_type_list @classmethod - async def add_dict_type_dao(cls, db: AsyncSession, dict_type: DictTypeModel): + async def add_dict_type_dao(cls, db: AsyncSession, dict_type: DictTypeModel) -> SysDictType: """ 新增字典类型数据库操作 @@ -107,7 +115,7 @@ class DictTypeDao: return db_dict_type @classmethod - async def edit_dict_type_dao(cls, db: AsyncSession, dict_type: dict): + async def edit_dict_type_dao(cls, db: AsyncSession, dict_type: dict) -> None: """ 编辑字典类型数据库操作 @@ -118,7 +126,7 @@ class DictTypeDao: await db.execute(update(SysDictType), [dict_type]) @classmethod - async def delete_dict_type_dao(cls, db: AsyncSession, dict_type: DictTypeModel): + async def delete_dict_type_dao(cls, db: AsyncSession, dict_type: DictTypeModel) -> None: """ 删除字典类型数据库操作 @@ -135,7 +143,7 @@ class DictDataDao: """ @classmethod - async def get_dict_data_detail_by_id(cls, db: AsyncSession, dict_code: int): + async def get_dict_data_detail_by_id(cls, db: AsyncSession, dict_code: int) -> Union[SysDictData, None]: """ 根据字典数据id获取字典数据详细信息 @@ -150,7 +158,7 @@ class DictDataDao: return dict_data_info @classmethod - async def get_dict_data_detail_by_info(cls, db: AsyncSession, dict_data: DictDataModel): + async def get_dict_data_detail_by_info(cls, db: AsyncSession, dict_data: DictDataModel) -> Union[SysDictData, None]: """ 根据字典数据参数获取字典数据信息 @@ -175,7 +183,9 @@ class DictDataDao: return dict_data_info @classmethod - async def get_dict_data_list(cls, db: AsyncSession, query_object: DictDataPageQueryModel, is_page: bool = False): + async def get_dict_data_list( + cls, db: AsyncSession, query_object: DictDataPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取字典数据列表信息 @@ -194,12 +204,14 @@ class DictDataDao: .order_by(SysDictData.dict_sort) .distinct() ) - dict_data_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + dict_data_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return dict_data_list @classmethod - async def query_dict_data_list(cls, db: AsyncSession, dict_type: str): + async def query_dict_data_list(cls, db: AsyncSession, dict_type: str) -> Sequence[SysDictData]: """ 根据查询参数获取字典数据列表信息 @@ -229,7 +241,7 @@ class DictDataDao: return dict_data_list @classmethod - async def add_dict_data_dao(cls, db: AsyncSession, dict_data: DictDataModel): + async def add_dict_data_dao(cls, db: AsyncSession, dict_data: DictDataModel) -> SysDictData: """ 新增字典数据数据库操作 @@ -244,7 +256,7 @@ class DictDataDao: return db_data_type @classmethod - async def edit_dict_data_dao(cls, db: AsyncSession, dict_data: dict): + async def edit_dict_data_dao(cls, db: AsyncSession, dict_data: dict) -> None: """ 编辑字典数据数据库操作 @@ -255,7 +267,7 @@ class DictDataDao: await db.execute(update(SysDictData), [dict_data]) @classmethod - async def delete_dict_data_dao(cls, db: AsyncSession, dict_data: DictDataModel): + async def delete_dict_data_dao(cls, db: AsyncSession, dict_data: DictDataModel) -> None: """ 删除字典数据数据库操作 @@ -266,7 +278,7 @@ class DictDataDao: await db.execute(delete(SysDictData).where(SysDictData.dict_code.in_([dict_data.dict_code]))) @classmethod - async def count_dict_data_dao(cls, db: AsyncSession, dict_type: str): + async def count_dict_data_dao(cls, db: AsyncSession, dict_type: str) -> Union[int, None]: """ 根据字典类型查询字典类型关联的字典数据数量 diff --git a/ruoyi-fastapi-backend/module_admin/dao/job_dao.py b/ruoyi-fastapi-backend/module_admin/dao/job_dao.py index fc30048..2b73d74 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/job_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/job_dao.py @@ -1,8 +1,12 @@ +from collections.abc import Sequence +from typing import Any, Union + from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.job_do import SysJob from module_admin.entity.vo.job_vo import JobModel, JobPageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class JobDao: @@ -11,7 +15,7 @@ class JobDao: """ @classmethod - async def get_job_detail_by_id(cls, db: AsyncSession, job_id: int): + async def get_job_detail_by_id(cls, db: AsyncSession, job_id: int) -> Union[SysJob, None]: """ 根据定时任务id获取定时任务详细信息 @@ -24,7 +28,7 @@ class JobDao: return job_info @classmethod - async def get_job_detail_by_info(cls, db: AsyncSession, job: JobModel): + async def get_job_detail_by_info(cls, db: AsyncSession, job: JobModel) -> Union[SysJob, None]: """ 根据定时任务参数获取定时任务信息 @@ -53,7 +57,9 @@ class JobDao: return job_info @classmethod - async def get_job_list(cls, db: AsyncSession, query_object: JobPageQueryModel, is_page: bool = False): + async def get_job_list( + cls, db: AsyncSession, query_object: JobPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取定时任务列表信息 @@ -72,12 +78,14 @@ class JobDao: .order_by(SysJob.job_id) .distinct() ) - job_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + job_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return job_list @classmethod - async def get_job_list_for_scheduler(cls, db: AsyncSession): + async def get_job_list_for_scheduler(cls, db: AsyncSession) -> Sequence[SysJob]: """ 获取定时任务列表信息 @@ -89,7 +97,7 @@ class JobDao: return job_list @classmethod - async def add_job_dao(cls, db: AsyncSession, job: JobModel): + async def add_job_dao(cls, db: AsyncSession, job: JobModel) -> SysJob: """ 新增定时任务数据库操作 @@ -104,7 +112,7 @@ class JobDao: return db_job @classmethod - async def edit_job_dao(cls, db: AsyncSession, job: dict, old_job: JobModel): + async def edit_job_dao(cls, db: AsyncSession, job: dict, old_job: JobModel) -> None: """ 编辑定时任务数据库操作 @@ -124,7 +132,7 @@ class JobDao: ) @classmethod - async def delete_job_dao(cls, db: AsyncSession, job: JobModel): + async def delete_job_dao(cls, db: AsyncSession, job: JobModel) -> None: """ 删除定时任务数据库操作 diff --git a/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py b/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py index 586a3d6..604a7fe 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py @@ -1,10 +1,13 @@ from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session + from module_admin.entity.do.job_do import SysJobLog from module_admin.entity.vo.job_vo import JobLogModel, JobLogPageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class JobLogDao: @@ -13,7 +16,9 @@ class JobLogDao: """ @classmethod - async def get_job_log_list(cls, db: AsyncSession, query_object: JobLogPageQueryModel, is_page: bool = False): + async def get_job_log_list( + cls, db: AsyncSession, query_object: JobLogPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取定时任务日志列表信息 @@ -38,12 +43,14 @@ class JobLogDao: .order_by(desc(SysJobLog.create_time)) .distinct() ) - job_log_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + job_log_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return job_log_list @classmethod - def add_job_log_dao(cls, db: Session, job_log: JobLogModel): + def add_job_log_dao(cls, db: Session, job_log: JobLogModel) -> SysJobLog: """ 新增定时任务日志数据库操作 @@ -58,7 +65,7 @@ class JobLogDao: return db_job_log @classmethod - async def delete_job_log_dao(cls, db: AsyncSession, job_log: JobLogModel): + async def delete_job_log_dao(cls, db: AsyncSession, job_log: JobLogModel) -> None: """ 删除定时任务日志数据库操作 @@ -69,7 +76,7 @@ class JobLogDao: await db.execute(delete(SysJobLog).where(SysJobLog.job_log_id.in_([job_log.job_log_id]))) @classmethod - async def clear_job_log_dao(cls, db: AsyncSession): + async def clear_job_log_dao(cls, db: AsyncSession) -> None: """ 清除定时任务日志数据库操作 diff --git a/ruoyi-fastapi-backend/module_admin/dao/log_dao.py b/ruoyi-fastapi-backend/module_admin/dao/log_dao.py index 684f3d7..385b155 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/log_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/log_dao.py @@ -1,10 +1,13 @@ from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import asc, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.log_do import SysLogininfor, SysOperLog from module_admin.entity.vo.log_vo import LogininforModel, LoginLogPageQueryModel, OperLogModel, OperLogPageQueryModel from utils.common_util import SnakeCaseUtil -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil from utils.time_format_util import TimeFormatUtil @@ -14,7 +17,9 @@ class OperationLogDao: """ @classmethod - async def get_operation_log_list(cls, db: AsyncSession, query_object: OperLogPageQueryModel, is_page: bool = False): + async def get_operation_log_list( + cls, db: AsyncSession, query_object: OperLogPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取操作日志列表信息 @@ -48,12 +53,14 @@ class OperationLogDao: .distinct() .order_by(order_by_column) ) - operation_log_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + operation_log_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return operation_log_list @classmethod - async def add_operation_log_dao(cls, db: AsyncSession, operation_log: OperLogModel): + async def add_operation_log_dao(cls, db: AsyncSession, operation_log: OperLogModel) -> SysOperLog: """ 新增操作日志数据库操作 @@ -68,7 +75,7 @@ class OperationLogDao: return db_operation_log @classmethod - async def delete_operation_log_dao(cls, db: AsyncSession, operation_log: OperLogModel): + async def delete_operation_log_dao(cls, db: AsyncSession, operation_log: OperLogModel) -> None: """ 删除操作日志数据库操作 @@ -79,7 +86,7 @@ class OperationLogDao: await db.execute(delete(SysOperLog).where(SysOperLog.oper_id.in_([operation_log.oper_id]))) @classmethod - async def clear_operation_log_dao(cls, db: AsyncSession): + async def clear_operation_log_dao(cls, db: AsyncSession) -> None: """ 清除操作日志数据库操作 @@ -95,7 +102,9 @@ class LoginLogDao: """ @classmethod - async def get_login_log_list(cls, db: AsyncSession, query_object: LoginLogPageQueryModel, is_page: bool = False): + async def get_login_log_list( + cls, db: AsyncSession, query_object: LoginLogPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取登录日志列表信息 @@ -130,12 +139,14 @@ class LoginLogDao: .distinct() .order_by(order_by_column) ) - login_log_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + login_log_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return login_log_list @classmethod - async def add_login_log_dao(cls, db: AsyncSession, login_log: LogininforModel): + async def add_login_log_dao(cls, db: AsyncSession, login_log: LogininforModel) -> SysLogininfor: """ 新增登录日志数据库操作 @@ -150,7 +161,7 @@ class LoginLogDao: return db_login_log @classmethod - async def delete_login_log_dao(cls, db: AsyncSession, login_log: LogininforModel): + async def delete_login_log_dao(cls, db: AsyncSession, login_log: LogininforModel) -> None: """ 删除登录日志数据库操作 @@ -161,7 +172,7 @@ class LoginLogDao: await db.execute(delete(SysLogininfor).where(SysLogininfor.info_id.in_([login_log.info_id]))) @classmethod - async def clear_login_log_dao(cls, db: AsyncSession): + async def clear_login_log_dao(cls, db: AsyncSession) -> None: """ 清除登录日志数据库操作 diff --git a/ruoyi-fastapi-backend/module_admin/dao/login_dao.py b/ruoyi-fastapi-backend/module_admin/dao/login_dao.py index 9764a4a..322c1c8 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/login_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/login_dao.py @@ -1,10 +1,13 @@ -from sqlalchemy import and_, select +from typing import Union + +from sqlalchemy import Row, and_, select from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.user_do import SysUser -async def login_by_account(db: AsyncSession, user_name: str): +async def login_by_account(db: AsyncSession, user_name: str) -> Union[Row[tuple[SysUser, SysDept]], None]: """ 根据用户名查询用户信息 diff --git a/ruoyi-fastapi-backend/module_admin/dao/menu_dao.py b/ruoyi-fastapi-backend/module_admin/dao/menu_dao.py index 19831e0..6343606 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/menu_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/menu_dao.py @@ -1,5 +1,9 @@ +from collections.abc import Sequence +from typing import Union + from sqlalchemy import and_, delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.menu_do import SysMenu from module_admin.entity.do.role_do import SysRole, SysRoleMenu from module_admin.entity.do.user_do import SysUser, SysUserRole @@ -12,7 +16,7 @@ class MenuDao: """ @classmethod - async def get_menu_detail_by_id(cls, db: AsyncSession, menu_id: int): + async def get_menu_detail_by_id(cls, db: AsyncSession, menu_id: int) -> Union[SysMenu, None]: """ 根据菜单id获取菜单详细信息 @@ -25,7 +29,7 @@ class MenuDao: return menu_info @classmethod - async def get_menu_detail_by_info(cls, db: AsyncSession, menu: MenuModel): + async def get_menu_detail_by_info(cls, db: AsyncSession, menu: MenuModel) -> Union[SysMenu, None]: """ 根据菜单参数获取菜单信息 @@ -50,7 +54,7 @@ class MenuDao: return menu_info @classmethod - async def get_menu_list_for_tree(cls, db: AsyncSession, user_id: int, role: list): + async def get_menu_list_for_tree(cls, db: AsyncSession, user_id: int, role: list) -> Sequence[SysMenu]: """ 根据角色信息获取所有在用菜单列表信息 @@ -94,7 +98,9 @@ class MenuDao: return menu_query_all @classmethod - async def get_menu_list(cls, db: AsyncSession, page_object: MenuQueryModel, user_id: int, role: list): + async def get_menu_list( + cls, db: AsyncSession, page_object: MenuQueryModel, user_id: int, role: list + ) -> Sequence[SysMenu]: """ 根据查询参数获取菜单列表信息 @@ -156,7 +162,7 @@ class MenuDao: return menu_query_all @classmethod - async def add_menu_dao(cls, db: AsyncSession, menu: MenuModel): + async def add_menu_dao(cls, db: AsyncSession, menu: MenuModel) -> SysMenu: """ 新增菜单数据库操作 @@ -171,7 +177,7 @@ class MenuDao: return db_menu @classmethod - async def edit_menu_dao(cls, db: AsyncSession, menu: dict): + async def edit_menu_dao(cls, db: AsyncSession, menu: dict) -> None: """ 编辑菜单数据库操作 @@ -182,7 +188,7 @@ class MenuDao: await db.execute(update(SysMenu), [menu]) @classmethod - async def delete_menu_dao(cls, db: AsyncSession, menu: MenuModel): + async def delete_menu_dao(cls, db: AsyncSession, menu: MenuModel) -> None: """ 删除菜单数据库操作 @@ -193,7 +199,7 @@ class MenuDao: await db.execute(delete(SysMenu).where(SysMenu.menu_id.in_([menu.menu_id]))) @classmethod - async def has_child_by_menu_id_dao(cls, db: AsyncSession, menu_id: int): + async def has_child_by_menu_id_dao(cls, db: AsyncSession, menu_id: int) -> Union[int, None]: """ 根据菜单id查询菜单关联子菜单的数量 @@ -208,7 +214,7 @@ class MenuDao: return menu_count @classmethod - async def check_menu_exist_role_dao(cls, db: AsyncSession, menu_id: int): + async def check_menu_exist_role_dao(cls, db: AsyncSession, menu_id: int) -> Union[int, None]: """ 根据菜单id查询菜单关联角色数量 diff --git a/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py b/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py index 9f48a14..b078555 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py @@ -1,9 +1,12 @@ from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.notice_do import SysNotice from module_admin.entity.vo.notice_vo import NoticeModel, NoticePageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class NoticeDao: @@ -12,7 +15,7 @@ class NoticeDao: """ @classmethod - async def get_notice_detail_by_id(cls, db: AsyncSession, notice_id: int): + async def get_notice_detail_by_id(cls, db: AsyncSession, notice_id: int) -> Union[SysNotice, None]: """ 根据通知公告id获取通知公告详细信息 @@ -25,7 +28,7 @@ class NoticeDao: return notice_info @classmethod - async def get_notice_detail_by_info(cls, db: AsyncSession, notice: NoticeModel): + async def get_notice_detail_by_info(cls, db: AsyncSession, notice: NoticeModel) -> Union[SysNotice, None]: """ 根据通知公告参数获取通知公告信息 @@ -50,7 +53,9 @@ class NoticeDao: return notice_info @classmethod - async def get_notice_list(cls, db: AsyncSession, query_object: NoticePageQueryModel, is_page: bool = False): + async def get_notice_list( + cls, db: AsyncSession, query_object: NoticePageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取通知公告列表信息 @@ -75,12 +80,14 @@ class NoticeDao: .order_by(SysNotice.notice_id) .distinct() ) - notice_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + notice_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return notice_list @classmethod - async def add_notice_dao(cls, db: AsyncSession, notice: NoticeModel): + async def add_notice_dao(cls, db: AsyncSession, notice: NoticeModel) -> SysNotice: """ 新增通知公告数据库操作 @@ -95,7 +102,7 @@ class NoticeDao: return db_notice @classmethod - async def edit_notice_dao(cls, db: AsyncSession, notice: dict): + async def edit_notice_dao(cls, db: AsyncSession, notice: dict) -> None: """ 编辑通知公告数据库操作 @@ -106,7 +113,7 @@ class NoticeDao: await db.execute(update(SysNotice), [notice]) @classmethod - async def delete_notice_dao(cls, db: AsyncSession, notice: NoticeModel): + async def delete_notice_dao(cls, db: AsyncSession, notice: NoticeModel) -> None: """ 删除通知公告数据库操作 diff --git a/ruoyi-fastapi-backend/module_admin/dao/post_dao.py b/ruoyi-fastapi-backend/module_admin/dao/post_dao.py index 7d90088..3ea0b22 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/post_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/post_dao.py @@ -1,9 +1,12 @@ +from typing import Any, Union + from sqlalchemy import delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.post_do import SysPost from module_admin.entity.do.user_do import SysUserPost from module_admin.entity.vo.post_vo import PostModel, PostPageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class PostDao: @@ -12,7 +15,7 @@ class PostDao: """ @classmethod - async def get_post_by_id(cls, db: AsyncSession, post_id: int): + async def get_post_by_id(cls, db: AsyncSession, post_id: int) -> Union[SysPost, None]: """ 根据岗位id获取在用岗位详细信息 @@ -29,7 +32,7 @@ class PostDao: return post_info @classmethod - async def get_post_detail_by_id(cls, db: AsyncSession, post_id: int): + async def get_post_detail_by_id(cls, db: AsyncSession, post_id: int) -> Union[SysPost, None]: """ 根据岗位id获取岗位详细信息 @@ -42,7 +45,7 @@ class PostDao: return post_info @classmethod - async def get_post_detail_by_info(cls, db: AsyncSession, post: PostModel): + async def get_post_detail_by_info(cls, db: AsyncSession, post: PostModel) -> Union[SysPost, None]: """ 根据岗位参数获取岗位信息 @@ -67,7 +70,9 @@ class PostDao: return post_info @classmethod - async def get_post_list(cls, db: AsyncSession, query_object: PostPageQueryModel, is_page: bool = False): + async def get_post_list( + cls, db: AsyncSession, query_object: PostPageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取岗位列表信息 @@ -86,12 +91,14 @@ class PostDao: .order_by(SysPost.post_sort) .distinct() ) - post_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + post_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return post_list @classmethod - async def add_post_dao(cls, db: AsyncSession, post: PostModel): + async def add_post_dao(cls, db: AsyncSession, post: PostModel) -> SysPost: """ 新增岗位数据库操作 @@ -106,7 +113,7 @@ class PostDao: return db_post @classmethod - async def edit_post_dao(cls, db: AsyncSession, post: dict): + async def edit_post_dao(cls, db: AsyncSession, post: dict) -> None: """ 编辑岗位数据库操作 @@ -117,7 +124,7 @@ class PostDao: await db.execute(update(SysPost), [post]) @classmethod - async def delete_post_dao(cls, db: AsyncSession, post: PostModel): + async def delete_post_dao(cls, db: AsyncSession, post: PostModel) -> None: """ 删除岗位数据库操作 @@ -128,7 +135,7 @@ class PostDao: await db.execute(delete(SysPost).where(SysPost.post_id.in_([post.post_id]))) @classmethod - async def count_user_post_dao(cls, db: AsyncSession, post_id: int): + async def count_user_post_dao(cls, db: AsyncSession, post_id: int) -> Union[int, None]: """ 根据岗位id查询岗位关联的用户数量 diff --git a/ruoyi-fastapi-backend/module_admin/dao/role_dao.py b/ruoyi-fastapi-backend/module_admin/dao/role_dao.py index 534c7f3..cc9366c 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/role_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/role_dao.py @@ -1,12 +1,16 @@ +from collections.abc import Sequence from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import and_, delete, desc, func, or_, select, update # noqa: F401 from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.menu_do import SysMenu -from module_admin.entity.do.role_do import SysRole, SysRoleMenu, SysRoleDept +from module_admin.entity.do.role_do import SysRole, SysRoleDept, SysRoleMenu from module_admin.entity.do.user_do import SysUser, SysUserRole from module_admin.entity.vo.role_vo import RoleDeptModel, RoleMenuModel, RoleModel, RolePageQueryModel -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class RoleDao: @@ -15,7 +19,7 @@ class RoleDao: """ @classmethod - async def get_role_by_name(cls, db: AsyncSession, role_name: str): + async def get_role_by_name(cls, db: AsyncSession, role_name: str) -> Union[SysRole, None]: """ 根据角色名获取在用角色信息 @@ -39,7 +43,7 @@ class RoleDao: return query_role_info @classmethod - async def get_role_by_info(cls, db: AsyncSession, role: RoleModel): + async def get_role_by_info(cls, db: AsyncSession, role: RoleModel) -> Union[SysRole, None]: """ 根据角色参数获取角色信息 @@ -67,7 +71,7 @@ class RoleDao: return query_role_info @classmethod - async def get_role_by_id(cls, db: AsyncSession, role_id: int): + async def get_role_by_id(cls, db: AsyncSession, role_id: int) -> Union[SysRole, None]: """ 根据角色id获取在用角色信息 @@ -88,7 +92,7 @@ class RoleDao: return role_info @classmethod - async def get_role_detail_by_id(cls, db: AsyncSession, role_id: int): + async def get_role_detail_by_id(cls, db: AsyncSession, role_id: int) -> Union[SysRole, None]: """ 根据role_id获取角色详细信息 @@ -105,7 +109,7 @@ class RoleDao: return query_role_info @classmethod - async def get_role_select_option_dao(cls, db: AsyncSession): + async def get_role_select_option_dao(cls, db: AsyncSession) -> Sequence[SysRole]: """ 获取编辑页面对应的在用角色列表信息 @@ -127,7 +131,7 @@ class RoleDao: @classmethod async def get_role_list( cls, db: AsyncSession, query_object: RolePageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取角色列表信息 @@ -159,12 +163,14 @@ class RoleDao: .order_by(SysRole.role_sort) .distinct() ) - role_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + role_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return role_list @classmethod - async def add_role_dao(cls, db: AsyncSession, role: RoleModel): + async def add_role_dao(cls, db: AsyncSession, role: RoleModel) -> SysRole: """ 新增角色数据库操作 @@ -179,7 +185,7 @@ class RoleDao: return db_role @classmethod - async def edit_role_dao(cls, db: AsyncSession, role: dict): + async def edit_role_dao(cls, db: AsyncSession, role: dict) -> None: """ 编辑角色数据库操作 @@ -190,7 +196,7 @@ class RoleDao: await db.execute(update(SysRole), [role]) @classmethod - async def delete_role_dao(cls, db: AsyncSession, role: RoleModel): + async def delete_role_dao(cls, db: AsyncSession, role: RoleModel) -> None: """ 删除角色数据库操作 @@ -205,7 +211,7 @@ class RoleDao: ) @classmethod - async def get_role_menu_dao(cls, db: AsyncSession, role: RoleModel): + async def get_role_menu_dao(cls, db: AsyncSession, role: RoleModel) -> Sequence[SysMenu]: """ 根据角色id获取角色菜单关联列表信息 @@ -241,7 +247,7 @@ class RoleDao: return role_menu_query_all @classmethod - async def add_role_menu_dao(cls, db: AsyncSession, role_menu: RoleMenuModel): + async def add_role_menu_dao(cls, db: AsyncSession, role_menu: RoleMenuModel) -> None: """ 新增角色菜单关联信息数据库操作 @@ -253,7 +259,7 @@ class RoleDao: db.add(db_role_menu) @classmethod - async def delete_role_menu_dao(cls, db: AsyncSession, role_menu: RoleMenuModel): + async def delete_role_menu_dao(cls, db: AsyncSession, role_menu: RoleMenuModel) -> None: """ 删除角色菜单关联信息数据库操作 @@ -264,7 +270,7 @@ class RoleDao: await db.execute(delete(SysRoleMenu).where(SysRoleMenu.role_id.in_([role_menu.role_id]))) @classmethod - async def get_role_dept_dao(cls, db: AsyncSession, role: RoleModel): + async def get_role_dept_dao(cls, db: AsyncSession, role: RoleModel) -> Sequence[SysDept]: """ 根据角色id获取角色部门关联列表信息 @@ -300,7 +306,7 @@ class RoleDao: return role_dept_query_all @classmethod - async def add_role_dept_dao(cls, db: AsyncSession, role_dept: RoleDeptModel): + async def add_role_dept_dao(cls, db: AsyncSession, role_dept: RoleDeptModel) -> None: """ 新增角色部门关联信息数据库操作 @@ -312,7 +318,7 @@ class RoleDao: db.add(db_role_dept) @classmethod - async def delete_role_dept_dao(cls, db: AsyncSession, role_dept: RoleDeptModel): + async def delete_role_dept_dao(cls, db: AsyncSession, role_dept: RoleDeptModel) -> None: """ 删除角色部门关联信息数据库操作 @@ -323,7 +329,7 @@ class RoleDao: await db.execute(delete(SysRoleDept).where(SysRoleDept.role_id.in_([role_dept.role_id]))) @classmethod - async def count_user_role_dao(cls, db: AsyncSession, role_id: int): + async def count_user_role_dao(cls, db: AsyncSession, role_id: int) -> Union[int, None]: """ 根据角色id查询角色关联用户数量 diff --git a/ruoyi-fastapi-backend/module_admin/dao/user_dao.py b/ruoyi-fastapi-backend/module_admin/dao/user_dao.py index cc53566..0442426 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/user_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/user_dao.py @@ -1,6 +1,10 @@ +from collections.abc import Sequence from datetime import datetime, time +from typing import Any, Union + from sqlalchemy import and_, delete, desc, func, or_, select, update from sqlalchemy.ext.asyncio import AsyncSession + from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.menu_do import SysMenu from module_admin.entity.do.post_do import SysPost @@ -14,7 +18,7 @@ from module_admin.entity.vo.user_vo import ( UserRolePageQueryModel, UserRoleQueryModel, ) -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class UserDao: @@ -23,7 +27,7 @@ class UserDao: """ @classmethod - async def get_user_by_name(cls, db: AsyncSession, user_name: str): + async def get_user_by_name(cls, db: AsyncSession, user_name: str) -> Union[SysUser, None]: """ 根据用户名获取用户信息 @@ -47,7 +51,7 @@ class UserDao: return query_user_info @classmethod - async def get_user_by_info(cls, db: AsyncSession, user: UserModel): + async def get_user_by_info(cls, db: AsyncSession, user: UserModel) -> Union[SysUser, None]: """ 根据用户参数获取用户信息 @@ -76,7 +80,7 @@ class UserDao: return query_user_info @classmethod - async def get_user_by_id(cls, db: AsyncSession, user_id: int): + async def get_user_by_id(cls, db: AsyncSession, user_id: int) -> dict[str, Any]: """ 根据user_id获取用户信息 @@ -172,18 +176,18 @@ class UserDao: .all() ) - results = dict( - user_basic_info=query_user_basic_info, - user_dept_info=query_user_dept_info, - user_role_info=query_user_role_info, - user_post_info=query_user_post_info, - user_menu_info=query_user_menu_info, - ) + results = { + 'user_basic_info': query_user_basic_info, + 'user_dept_info': query_user_dept_info, + 'user_role_info': query_user_role_info, + 'user_post_info': query_user_post_info, + 'user_menu_info': query_user_menu_info, + } return results @classmethod - async def get_user_detail_by_id(cls, db: AsyncSession, user_id: int): + async def get_user_detail_by_id(cls, db: AsyncSession, user_id: int) -> dict[str, Any]: """ 根据user_id获取用户详细信息 @@ -263,20 +267,20 @@ class UserDao: .scalars() .all() ) - results = dict( - user_basic_info=query_user_basic_info, - user_dept_info=query_user_dept_info, - user_role_info=query_user_role_info, - user_post_info=query_user_post_info, - user_menu_info=query_user_menu_info, - ) + results = { + 'user_basic_info': query_user_basic_info, + 'user_dept_info': query_user_dept_info, + 'user_role_info': query_user_role_info, + 'user_post_info': query_user_post_info, + 'user_menu_info': query_user_menu_info, + } return results @classmethod async def get_user_list( cls, db: AsyncSession, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[list[dict[str, Any]]]]: """ 根据查询参数获取用户列表信息 @@ -321,12 +325,14 @@ class UserDao: .order_by(SysUser.user_id) .distinct() ) - user_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + user_list: Union[PageResponseModel, list[list[dict[str, Any]]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return user_list @classmethod - async def add_user_dao(cls, db: AsyncSession, user: UserModel): + async def add_user_dao(cls, db: AsyncSession, user: UserModel) -> SysUser: """ 新增用户数据库操作 @@ -341,7 +347,7 @@ class UserDao: return db_user @classmethod - async def edit_user_dao(cls, db: AsyncSession, user: dict): + async def edit_user_dao(cls, db: AsyncSession, user: dict) -> None: """ 编辑用户数据库操作 @@ -352,7 +358,7 @@ class UserDao: await db.execute(update(SysUser), [user]) @classmethod - async def delete_user_dao(cls, db: AsyncSession, user: UserModel): + async def delete_user_dao(cls, db: AsyncSession, user: UserModel) -> None: """ 删除用户数据库操作 @@ -367,7 +373,9 @@ class UserDao: ) @classmethod - async def get_user_role_allocated_list_by_user_id(cls, db: AsyncSession, query_object: UserRoleQueryModel): + async def get_user_role_allocated_list_by_user_id( + cls, db: AsyncSession, query_object: UserRoleQueryModel + ) -> Sequence[SysRole]: """ 根据用户id获取用户已分配的角色列表信息数据库操作 @@ -400,7 +408,7 @@ class UserDao: @classmethod async def get_user_role_allocated_list_by_role_id( cls, db: AsyncSession, query_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据角色id获取已分配的用户列表信息 @@ -424,14 +432,16 @@ class UserDao: ) .distinct() ) - allocated_user_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + allocated_user_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return allocated_user_list @classmethod async def get_user_role_unallocated_list_by_role_id( cls, db: AsyncSession, query_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据角色id获取未分配的用户列表信息 @@ -463,14 +473,14 @@ class UserDao: ) .distinct() ) - unallocated_user_list = await PageUtil.paginate( + unallocated_user_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) return unallocated_user_list @classmethod - async def add_user_role_dao(cls, db: AsyncSession, user_role: UserRoleModel): + async def add_user_role_dao(cls, db: AsyncSession, user_role: UserRoleModel) -> None: """ 新增用户角色关联信息数据库操作 @@ -482,7 +492,7 @@ class UserDao: db.add(db_user_role) @classmethod - async def delete_user_role_dao(cls, db: AsyncSession, user_role: UserRoleModel): + async def delete_user_role_dao(cls, db: AsyncSession, user_role: UserRoleModel) -> None: """ 删除用户角色关联信息数据库操作 @@ -493,7 +503,7 @@ class UserDao: await db.execute(delete(SysUserRole).where(SysUserRole.user_id.in_([user_role.user_id]))) @classmethod - async def delete_user_role_by_user_and_role_dao(cls, db: AsyncSession, user_role: UserRoleModel): + async def delete_user_role_by_user_and_role_dao(cls, db: AsyncSession, user_role: UserRoleModel) -> None: """ 根据用户id及角色id删除用户角色关联信息数据库操作 @@ -509,7 +519,7 @@ class UserDao: ) @classmethod - async def get_user_role_detail(cls, db: AsyncSession, user_role: UserRoleModel): + async def get_user_role_detail(cls, db: AsyncSession, user_role: UserRoleModel) -> Union[SysUserRole, None]: """ 根据用户角色关联获取用户角色关联详细信息 @@ -532,7 +542,7 @@ class UserDao: return user_role_info @classmethod - async def add_user_post_dao(cls, db: AsyncSession, user_post: UserPostModel): + async def add_user_post_dao(cls, db: AsyncSession, user_post: UserPostModel) -> None: """ 新增用户岗位关联信息数据库操作 @@ -544,7 +554,7 @@ class UserDao: db.add(db_user_post) @classmethod - async def delete_user_post_dao(cls, db: AsyncSession, user_post: UserPostModel): + async def delete_user_post_dao(cls, db: AsyncSession, user_post: UserPostModel) -> None: """ 删除用户岗位关联信息数据库操作 @@ -555,7 +565,7 @@ class UserDao: await db.execute(delete(SysUserPost).where(SysUserPost.user_id.in_([user_post.user_id]))) @classmethod - async def get_user_dept_info(cls, db: AsyncSession, dept_id: int): + async def get_user_dept_info(cls, db: AsyncSession, dept_id: int) -> Union[SysDept, None]: dept_basic_info = ( ( await db.execute( diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/config_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/config_do.py index 8a3235d..0c40b8d 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/config_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/config_do.py @@ -1,5 +1,7 @@ from datetime import datetime + from sqlalchemy import CHAR, Column, DateTime, Integer, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/dept_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/dept_do.py index 48baf8d..c745b56 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/dept_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/dept_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, Integer, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/dict_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/dict_do.py index de6a9c4..37b2b7b 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/dict_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/dict_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, Integer, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py index b966066..6a19665 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, DOUBLE, Index, LargeBinary, String + +from sqlalchemy import CHAR, DOUBLE, BigInteger, Column, DateTime, Index, LargeBinary, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/log_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/log_do.py index 981b026..298921c 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/log_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/log_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, Index, Integer, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Index, Integer, String + from config.database import Base @@ -38,7 +40,9 @@ class SysOperLog(Base): business_type = Column(Integer, nullable=True, server_default='0', comment='业务类型(0其它 1新增 2修改 3删除)') method = Column(String(100), nullable=True, server_default="''", comment='方法名称') request_method = Column(String(10), nullable=True, server_default="''", comment='请求方式') - operator_type = Column(Integer, nullable=True, server_default='0', comment='操作类别(0其它 1后台用户 2手机端用户)') + operator_type = Column( + Integer, nullable=True, server_default='0', comment='操作类别(0其它 1后台用户 2手机端用户)' + ) oper_name = Column(String(50), nullable=True, server_default="''", comment='操作人员') dept_name = Column(String(50), nullable=True, server_default="''", comment='部门名称') oper_url = Column(String(255), nullable=True, server_default="''", comment='请求URL') diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/menu_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/menu_do.py index 0a8a836..b7aa4c7 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/menu_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/menu_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, Integer, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/notice_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/notice_do.py index 0d60854..468f599 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/notice_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/notice_do.py @@ -1,6 +1,8 @@ from datetime import datetime + from sqlalchemy import CHAR, Column, DateTime, Integer, LargeBinary, String from sqlalchemy.dialects import mysql + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/post_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/post_do.py index 442d0f3..5b18596 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/post_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/post_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, Integer, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/role_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/role_do.py index fecf9d1..39b0866 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/role_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/role_do.py @@ -1,6 +1,8 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, Integer, SmallInteger, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, SmallInteger, String from sqlalchemy.dialects import mysql + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py index c71b5b7..4d1cfe1 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py @@ -1,5 +1,7 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, String + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/cache_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/cache_vo.py index 79b49fb..dfd4669 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/cache_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/cache_vo.py @@ -1,6 +1,7 @@ +from typing import Any, Optional + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel -from typing import Any, List, Optional class CacheMonitorModel(BaseModel): @@ -10,7 +11,7 @@ class CacheMonitorModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - command_stats: Optional[List] = Field(default=[], description='命令统计') + command_stats: Optional[list] = Field(default=[], description='命令统计') db_size: Optional[int] = Field(default=None, description='Key数量') info: Optional[dict] = Field(default={}, description='Redis信息') diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py index 258be5d..f885c31 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py @@ -1,6 +1,7 @@ +from typing import Any, Optional + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel -from typing import Any, Optional class CrudResponseModel(BaseModel): diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/config_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/config_vo.py index 917d7d6..395c608 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/config_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/config_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Size -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class ConfigModel(BaseModel): @@ -26,20 +26,20 @@ class ConfigModel(BaseModel): @NotBlank(field_name='config_key', message='参数名称不能为空') @Size(field_name='config_key', min_length=0, max_length=100, message='参数名称长度不能超过100个字符') - def get_config_key(self): + def get_config_key(self) -> Union[str, None]: return self.config_key @NotBlank(field_name='config_name', message='参数键名不能为空') @Size(field_name='config_name', min_length=0, max_length=100, message='参数键名长度不能超过100个字符') - def get_config_name(self): + def get_config_name(self) -> Union[str, None]: return self.config_name @NotBlank(field_name='config_value', message='参数键值不能为空') @Size(field_name='config_value', min_length=0, max_length=500, message='参数键值长度不能超过500个字符') - def get_config_value(self): + def get_config_value(self) -> Union[str, None]: return self.config_value - def validate_fields(self): + def validate_fields(self) -> None: self.get_config_key() self.get_config_name() self.get_config_value() @@ -54,7 +54,6 @@ class ConfigQueryModel(ConfigModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class ConfigPageQueryModel(ConfigQueryModel): """ 参数配置管理分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py index dcad117..930f820 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import Network, NotBlank, Size -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class DeptModel(BaseModel): @@ -30,30 +30,29 @@ class DeptModel(BaseModel): @NotBlank(field_name='dept_name', message='部门名称不能为空') @Size(field_name='dept_name', min_length=0, max_length=30, message='部门名称长度不能超过30个字符') - def get_dept_name(self): + def get_dept_name(self) -> Union[str, None]: return self.dept_name @NotBlank(field_name='order_num', message='显示顺序不能为空') - def get_order_num(self): + def get_order_num(self) -> Union[int, None]: return self.order_num @Size(field_name='phone', min_length=0, max_length=11, message='联系电话长度不能超过11个字符') - def get_phone(self): + def get_phone(self) -> Union[str, None]: return self.phone @Network(field_name='email', field_type='EmailStr', message='邮箱格式不正确') @Size(field_name='email', min_length=0, max_length=50, message='邮箱长度不能超过50个字符') - def get_email(self): + def get_email(self) -> Union[str, None]: return self.email - def validate_fields(self): + def validate_fields(self) -> None: self.get_dept_name() self.get_order_num() self.get_phone() self.get_email() -@as_query class DeptQueryModel(DeptModel): """ 部门管理不分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/dict_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/dict_vo.py index 3251f08..3d9a463 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/dict_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/dict_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Pattern, Size -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class DictTypeModel(BaseModel): @@ -25,7 +25,7 @@ class DictTypeModel(BaseModel): @NotBlank(field_name='dict_name', message='字典名称不能为空') @Size(field_name='dict_name', min_length=0, max_length=100, message='字典类型名称长度不能超过100个字符') - def get_dict_name(self): + def get_dict_name(self) -> Union[str, None]: return self.dict_name @NotBlank(field_name='dict_type', message='字典类型不能为空') @@ -35,10 +35,10 @@ class DictTypeModel(BaseModel): regexp='^[a-z][a-z0-9_]*$', message='字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)', ) - def get_dict_type(self): + def get_dict_type(self) -> Union[str, None]: return self.dict_type - def validate_fields(self): + def validate_fields(self) -> None: self.get_dict_name() self.get_dict_type() @@ -67,24 +67,24 @@ class DictDataModel(BaseModel): @NotBlank(field_name='dict_label', message='字典标签不能为空') @Size(field_name='dict_label', min_length=0, max_length=100, message='字典标签长度不能超过100个字符') - def get_dict_label(self): + def get_dict_label(self) -> Union[str, None]: return self.dict_label @NotBlank(field_name='dict_value', message='字典键值不能为空') @Size(field_name='dict_value', min_length=0, max_length=100, message='字典键值长度不能超过100个字符') - def get_dict_value(self): + def get_dict_value(self) -> Union[str, None]: return self.dict_value @NotBlank(field_name='dict_type', message='字典类型不能为空') @Size(field_name='dict_type', min_length=0, max_length=100, message='字典类型长度不能超过100个字符') - def get_dict_type(self): + def get_dict_type(self) -> Union[str, None]: return self.dict_type @Size(field_name='css_class', min_length=0, max_length=100, message='样式属性长度不能超过100个字符') - def get_css_class(self): + def get_css_class(self) -> Union[str, None]: return self.css_class - def validate_fields(self): + def validate_fields(self) -> None: self.get_dict_label() self.get_dict_value() self.get_dict_type() @@ -100,7 +100,6 @@ class DictTypeQueryModel(DictTypeModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class DictTypePageQueryModel(DictTypeQueryModel): """ 字典类型管理分页查询模型 @@ -129,7 +128,6 @@ class DictDataQueryModel(DictDataModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class DictDataPageQueryModel(DictDataQueryModel): """ 字典数据管理分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/job_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/job_vo.py index 960a837..732ba8e 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/job_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/job_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Size -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class JobModel(BaseModel): @@ -34,15 +34,15 @@ class JobModel(BaseModel): @NotBlank(field_name='invoke_target', message='调用目标字符串不能为空') @Size(field_name='invoke_target', min_length=0, max_length=500, message='调用目标字符串长度不能超过500个字符') - def get_invoke_target(self): + def get_invoke_target(self) -> Union[str, None]: return self.invoke_target @NotBlank(field_name='cron_expression', message='Cron执行表达式不能为空') @Size(field_name='cron_expression', min_length=0, max_length=255, message='Cron执行表达式不能超过255个字符') - def get_cron_expression(self): + def get_cron_expression(self) -> Union[str, None]: return self.cron_expression - def validate_fields(self): + def validate_fields(self) -> None: self.get_invoke_target() self.get_cron_expression() @@ -77,7 +77,6 @@ class JobQueryModel(JobModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class JobPageQueryModel(JobQueryModel): """ 定时任务管理分页查询模型 @@ -114,7 +113,6 @@ class JobLogQueryModel(JobLogModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class JobLogPageQueryModel(JobLogQueryModel): """ 定时任务日志管理分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/log_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/log_vo.py index 739ad6c..3ad871a 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/log_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/log_vo.py @@ -1,8 +1,8 @@ from datetime import datetime +from typing import Literal, Optional + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class OperLogModel(BaseModel): @@ -68,7 +68,6 @@ class OperLogQueryModel(OperLogModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class OperLogPageQueryModel(OperLogQueryModel): """ 操作日志管理分页查询模型 @@ -101,7 +100,6 @@ class LoginLogQueryModel(LogininforModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class LoginLogPageQueryModel(LoginLogQueryModel): """ 登录日志管理分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py index fbd6e07..c86758b 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py @@ -1,7 +1,9 @@ import re +from typing import Optional, Union + from pydantic import BaseModel, ConfigDict, Field, model_validator from pydantic.alias_generators import to_camel -from typing import List, Optional, Union + from exceptions.exception import ModelValidatorException from module_admin.entity.vo.menu_vo import MenuModel @@ -31,8 +33,7 @@ class UserRegister(BaseModel): pattern = r"""^[^<>"'|\\]+$""" if self.password is None or re.match(pattern, self.password): return self - else: - raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') + raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') class Token(BaseModel): @@ -57,7 +58,7 @@ class SmsCode(BaseModel): class MenuTreeModel(MenuModel): - children: Optional[Union[List['MenuTreeModel'], None]] = Field(default=None, description='子菜单') + children: Optional[Union[list['MenuTreeModel'], None]] = Field(default=None, description='子菜单') class MetaModel(BaseModel): @@ -84,4 +85,4 @@ class RouterModel(BaseModel): default=None, description='当你一个路由下面的children声明的路由大于1个时,自动会变成嵌套的模式--如组件页面' ) meta: Optional[MetaModel] = Field(default=None, description='其他元素') - children: Optional[Union[List['RouterModel'], None]] = Field(default=None, description='子路由') + children: Optional[Union[list['RouterModel'], None]] = Field(default=None, description='子路由') diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py index 9dc8d75..b58500c 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Size -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class MenuModel(BaseModel): @@ -36,30 +36,30 @@ class MenuModel(BaseModel): @NotBlank(field_name='menu_name', message='菜单名称不能为空') @Size(field_name='menu_name', min_length=0, max_length=50, message='菜单名称长度不能超过50个字符') - def get_menu_name(self): + def get_menu_name(self) -> Union[str, None]: return self.menu_name @NotBlank(field_name='order_num', message='显示顺序不能为空') - def get_order_num(self): + def get_order_num(self) -> Union[int, None]: return self.order_num @Size(field_name='path', min_length=0, max_length=200, message='路由地址长度不能超过200个字符') - def get_path(self): + def get_path(self) -> Union[str, None]: return self.path @Size(field_name='component', min_length=0, max_length=255, message='组件路径长度不能超过255个字符') - def get_component(self): + def get_component(self) -> Union[str, None]: return self.component @NotBlank(field_name='menu_type', message='菜单类型不能为空') - def get_menu_type(self): + def get_menu_type(self) -> Union[Literal['M', 'C', 'F'], None]: return self.menu_type @Size(field_name='perms', min_length=0, max_length=100, message='权限标识长度不能超过100个字符') - def get_perms(self): + def get_perms(self) -> Union[str, None]: return self.perms - def validate_fields(self): + def validate_fields(self) -> None: self.get_menu_name() self.get_order_num() self.get_path() @@ -68,7 +68,6 @@ class MenuModel(BaseModel): self.get_perms() -@as_query class MenuQueryModel(MenuModel): """ 菜单管理不分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/notice_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/notice_vo.py index 0b5d70c..155530a 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/notice_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/notice_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Size, Xss -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class NoticeModel(BaseModel): @@ -27,10 +27,10 @@ class NoticeModel(BaseModel): @Xss(field_name='notice_title', message='公告标题不能包含脚本字符') @NotBlank(field_name='notice_title', message='公告标题不能为空') @Size(field_name='notice_title', min_length=0, max_length=50, message='公告标题不能超过50个字符') - def get_notice_title(self): + def get_notice_title(self) -> Union[str, None]: return self.notice_title - def validate_fields(self): + def validate_fields(self) -> None: self.get_notice_title() @@ -43,7 +43,6 @@ class NoticeQueryModel(NoticeModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class NoticePageQueryModel(NoticeQueryModel): """ 通知公告管理分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py index 11bb475..68eda31 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py @@ -1,8 +1,8 @@ from datetime import datetime +from typing import Optional + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel -from typing import Optional -from module_admin.annotation.pydantic_annotation import as_query class OnlineModel(BaseModel): @@ -22,7 +22,6 @@ class OnlineModel(BaseModel): login_time: Optional[datetime] = Field(default=None, description='登录时间') -@as_query class OnlineQueryModel(OnlineModel): """ 岗位管理不分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/post_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/post_vo.py index 79390c3..dcb4f3b 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/post_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/post_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Size -from typing import Literal, Optional -from module_admin.annotation.pydantic_annotation import as_query class PostModel(BaseModel): @@ -26,19 +26,19 @@ class PostModel(BaseModel): @NotBlank(field_name='post_code', message='岗位编码不能为空') @Size(field_name='post_code', min_length=0, max_length=64, message='岗位编码长度不能超过64个字符') - def get_post_code(self): + def get_post_code(self) -> Union[str, None]: return self.post_code @NotBlank(field_name='post_name', message='岗位名称不能为空') @Size(field_name='post_name', min_length=0, max_length=50, message='岗位名称长度不能超过50个字符') - def get_post_name(self): + def get_post_name(self) -> Union[str, None]: return self.post_name @NotBlank(field_name='post_sort', message='显示顺序不能为空') - def get_post_sort(self): + def get_post_sort(self) -> Union[int, None]: return self.post_sort - def validate_fields(self): + def validate_fields(self) -> None: self.get_post_code() self.get_post_name() self.get_post_sort() @@ -53,7 +53,6 @@ class PostQueryModel(PostModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class PostPageQueryModel(PostQueryModel): """ 岗位管理分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py index a81f8d5..5c80dd0 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/role_vo.py @@ -1,9 +1,9 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank, Size -from typing import List, Literal, Optional, Union -from module_admin.annotation.pydantic_annotation import as_query class RoleModel(BaseModel): @@ -55,19 +55,19 @@ class RoleModel(BaseModel): @NotBlank(field_name='role_name', message='角色名称不能为空') @Size(field_name='role_name', min_length=0, max_length=30, message='角色名称长度不能超过30个字符') - def get_role_name(self): + def get_role_name(self) -> Union[str, None]: return self.role_name @NotBlank(field_name='role_key', message='权限字符不能为空') @Size(field_name='role_key', min_length=0, max_length=100, message='权限字符长度不能超过100个字符') - def get_role_key(self): + def get_role_key(self) -> Union[str, None]: return self.role_key @NotBlank(field_name='role_sort', message='显示顺序不能为空') - def get_role_sort(self): + def get_role_sort(self) -> Union[int, None]: return self.role_sort - def validate_fields(self): + def validate_fields(self) -> None: self.get_role_name() self.get_role_key() self.get_role_sort() @@ -104,7 +104,6 @@ class RoleQueryModel(RoleModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class RolePageQueryModel(RoleQueryModel): """ 角色管理分页查询模型 @@ -121,8 +120,8 @@ class RoleMenuQueryModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - menus: List = Field(default=[], description='菜单信息') - checked_keys: List[int] = Field(default=[], description='已选择的菜单ID信息') + menus: list = Field(default=[], description='菜单信息') + checked_keys: list[int] = Field(default=[], description='已选择的菜单ID信息') class RoleDeptQueryModel(BaseModel): @@ -132,8 +131,8 @@ class RoleDeptQueryModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - depts: List = Field(default=[], description='部门信息') - checked_keys: List[int] = Field(default=[], description='已选择的部门ID信息') + depts: list = Field(default=[], description='部门信息') + checked_keys: list[int] = Field(default=[], description='已选择的部门ID信息') class AddRoleModel(RoleModel): @@ -141,8 +140,8 @@ class AddRoleModel(RoleModel): 新增角色模型 """ - dept_ids: List = Field(default=[], description='部门ID信息') - menu_ids: List = Field(default=[], description='菜单ID信息') + dept_ids: list = Field(default=[], description='部门ID信息') + menu_ids: list = Field(default=[], description='菜单ID信息') type: Optional[str] = Field(default=None, description='操作类型') @@ -153,6 +152,6 @@ class DeleteRoleModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - role_ids: str = Field(description='需要删除的菜单ID') + role_ids: str = Field(description='需要删除的角色ID') update_by: Optional[str] = Field(default=None, description='更新者') update_time: Optional[datetime] = Field(default=None, description='更新时间') diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/server_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/server_vo.py index 810ecac..52c63bf 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/server_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/server_vo.py @@ -1,6 +1,7 @@ +from typing import Optional + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel -from typing import List, Optional class CpuInfo(BaseModel): @@ -64,4 +65,4 @@ class ServerMonitorModel(BaseModel): py: Optional[PyInfo] = Field(description='Python相关信息') mem: Optional[MemoryInfo] = Field(description='內存相关信息') sys: Optional[SysInfo] = Field(description='服务器相关信息') - sys_files: Optional[List[SysFiles]] = Field(description='磁盘相关信息') + sys_files: Optional[list[SysFiles]] = Field(description='磁盘相关信息') diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py index 0230882..887b0f9 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py @@ -1,11 +1,12 @@ import re from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field, model_validator from pydantic.alias_generators import to_camel from pydantic_validation_decorator import Network, NotBlank, Size, Xss -from typing import List, Literal, Optional, Union + from exceptions.exception import ModelValidatorException -from module_admin.annotation.pydantic_annotation import as_query from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.post_vo import PostModel from module_admin.entity.vo.role_vo import RoleModel @@ -53,8 +54,7 @@ class UserModel(BaseModel): pattern = r"""^[^<>"'|\\]+$""" if self.password is None or re.match(pattern, self.password): return self - else: - raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') + raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') @model_validator(mode='after') def check_admin(self) -> 'UserModel': @@ -67,24 +67,24 @@ class UserModel(BaseModel): @Xss(field_name='user_name', message='用户账号不能包含脚本字符') @NotBlank(field_name='user_name', message='用户账号不能为空') @Size(field_name='user_name', min_length=0, max_length=30, message='用户账号长度不能超过30个字符') - def get_user_name(self): + def get_user_name(self) -> Union[str, None]: return self.user_name @Xss(field_name='nick_name', message='用户昵称不能包含脚本字符') @Size(field_name='nick_name', min_length=0, max_length=30, message='用户昵称长度不能超过30个字符') - def get_nick_name(self): + def get_nick_name(self) -> Union[str, None]: return self.nick_name @Network(field_name='email', field_type='EmailStr', message='邮箱格式不正确') @Size(field_name='email', min_length=0, max_length=50, message='邮箱长度不能超过50个字符') - def get_email(self): + def get_email(self) -> Union[str, None]: return self.email @Size(field_name='phonenumber', min_length=0, max_length=11, message='手机号码长度不能超过11个字符') - def get_phonenumber(self): + def get_phonenumber(self) -> Union[str, None]: return self.phonenumber - def validate_fields(self): + def validate_fields(self) -> None: self.get_user_name() self.get_nick_name() self.get_email() @@ -117,14 +117,14 @@ class UserInfoModel(UserModel): post_ids: Optional[Union[str, None]] = Field(default=None, description='岗位ID信息') role_ids: Optional[Union[str, None]] = Field(default=None, description='角色ID信息') dept: Optional[Union[DeptModel, None]] = Field(default=None, description='部门信息') - role: Optional[List[Union[RoleModel, None]]] = Field(default=[], description='角色信息') + role: Optional[list[Union[RoleModel, None]]] = Field(default=[], description='角色信息') class CurrentUserModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - permissions: List = Field(description='权限信息') - roles: List = Field(description='角色信息') + permissions: list = Field(description='权限信息') + roles: list = Field(description='角色信息') user: Union[UserInfoModel, None] = Field(description='用户信息') is_default_modify_pwd: bool = Field(default=False, description='是否初始密码修改提醒') is_password_expired: bool = Field(default=False, description='密码是否过期提醒') @@ -138,10 +138,10 @@ class UserDetailModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) data: Optional[Union[UserInfoModel, None]] = Field(default=None, description='用户信息') - post_ids: Optional[List] = Field(default=None, description='岗位ID信息') - posts: List[Union[PostModel, None]] = Field(description='岗位信息') - role_ids: Optional[List] = Field(default=None, description='角色ID信息') - roles: List[Union[RoleModel, None]] = Field(description='角色信息') + post_ids: Optional[list] = Field(default=None, description='岗位ID信息') + posts: list[Union[PostModel, None]] = Field(description='岗位信息') + role_ids: Optional[list] = Field(default=None, description='角色ID信息') + roles: list[Union[RoleModel, None]] = Field(description='角色信息') class UserProfileModel(BaseModel): @@ -165,7 +165,6 @@ class UserQueryModel(UserModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class UserPageQueryModel(UserQueryModel): """ 用户管理分页查询模型 @@ -180,8 +179,8 @@ class AddUserModel(UserModel): 新增用户模型 """ - role_ids: Optional[List] = Field(default=[], description='角色ID信息') - post_ids: Optional[List] = Field(default=[], description='岗位ID信息') + role_ids: Optional[list] = Field(default=[], description='角色ID信息') + post_ids: Optional[list] = Field(default=[], description='岗位ID信息') type: Optional[str] = Field(default=None, description='操作类型') @@ -190,7 +189,7 @@ class EditUserModel(AddUserModel): 编辑用户模型 """ - role: Optional[List] = Field(default=[], description='角色信息') + role: Optional[list] = Field(default=[], description='角色信息') class ResetPasswordModel(BaseModel): @@ -208,8 +207,7 @@ class ResetPasswordModel(BaseModel): pattern = r"""^[^<>"'|\\]+$""" if self.new_password is None or re.match(pattern, self.new_password): return self - else: - raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') + raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') class ResetUserModel(UserModel): @@ -242,7 +240,6 @@ class UserRoleQueryModel(UserModel): role_id: Optional[int] = Field(default=None, description='角色ID') -@as_query class UserRolePageQueryModel(UserRoleQueryModel): """ 用户角色关联管理分页查询模型 @@ -267,11 +264,10 @@ class UserRoleResponseModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - roles: List[Union[SelectedRoleModel, None]] = Field(default=[], description='角色信息') + roles: list[Union[SelectedRoleModel, None]] = Field(default=[], description='角色信息') user: UserInfoModel = Field(description='用户信息') -@as_query class CrudUserRoleModel(BaseModel): """ 新增、删除用户关联角色及角色关联用户模型 diff --git a/ruoyi-fastapi-backend/module_admin/service/cache_service.py b/ruoyi-fastapi-backend/module_admin/service/cache_service.py index 72212cb..27619a8 100644 --- a/ruoyi-fastapi-backend/module_admin/service/cache_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/cache_service.py @@ -1,4 +1,5 @@ from fastapi import Request + from config.enums import RedisInitKeyConfig from config.get_redis import RedisUtil from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel @@ -11,7 +12,7 @@ class CacheService: """ @classmethod - async def get_cache_monitor_statistical_info_services(cls, request: Request): + async def get_cache_monitor_statistical_info_services(cls, request: Request) -> CacheMonitorModel: """ 获取缓存监控信息service @@ -22,34 +23,33 @@ class CacheService: db_size = await request.app.state.redis.dbsize() command_stats_dict = await request.app.state.redis.info('commandstats') command_stats = [ - dict(name=key.split('_')[1], value=str(value.get('calls'))) for key, value in command_stats_dict.items() + {'name': key.split('_')[1], 'value': str(value.get('calls'))} for key, value in command_stats_dict.items() ] result = CacheMonitorModel(commandStats=command_stats, dbSize=db_size, info=info) return result @classmethod - async def get_cache_monitor_cache_name_services(cls): + async def get_cache_monitor_cache_name_services(cls) -> list[CacheInfoModel]: """ 获取缓存名称列表信息service :return: 缓存名称列表信息 """ - name_list = [] - for key_config in RedisInitKeyConfig: - name_list.append( - CacheInfoModel( - cacheKey='', - cacheName=key_config.key, - cacheValue='', - remark=key_config.remark, - ) + name_list = [ + CacheInfoModel( + cacheKey='', + cacheName=key_config.key, + cacheValue='', + remark=key_config.remark, ) + for key_config in RedisInitKeyConfig + ] return name_list @classmethod - async def get_cache_monitor_cache_key_services(cls, request: Request, cache_name: str): + async def get_cache_monitor_cache_key_services(cls, request: Request, cache_name: str) -> list[str]: """ 获取缓存键名列表信息service @@ -57,13 +57,15 @@ class CacheService: :param cache_name: 缓存名称 :return: 缓存键名列表信息 """ - cache_keys = await request.app.state.redis.keys(f'{cache_name}*') + cache_keys: list[str] = await request.app.state.redis.keys(f'{cache_name}*') cache_key_list = [key.split(':', 1)[1] for key in cache_keys if key.startswith(f'{cache_name}:')] return cache_key_list @classmethod - async def get_cache_monitor_cache_value_services(cls, request: Request, cache_name: str, cache_key: str): + async def get_cache_monitor_cache_value_services( + cls, request: Request, cache_name: str, cache_key: str + ) -> CacheInfoModel: """ 获取缓存内容信息service @@ -77,7 +79,7 @@ class CacheService: return CacheInfoModel(cacheKey=cache_key, cacheName=cache_name, cacheValue=cache_value, remark='') @classmethod - async def clear_cache_monitor_cache_name_services(cls, request: Request, cache_name: str): + async def clear_cache_monitor_cache_name_services(cls, request: Request, cache_name: str) -> CrudResponseModel: """ 清除缓存名称对应所有键值service @@ -92,7 +94,7 @@ class CacheService: return CrudResponseModel(is_success=True, message=f'{cache_name}对应键值清除成功') @classmethod - async def clear_cache_monitor_cache_key_services(cls, request: Request, cache_key: str): + async def clear_cache_monitor_cache_key_services(cls, request: Request, cache_key: str) -> CrudResponseModel: """ 清除缓存名称对应所有键值service @@ -107,7 +109,7 @@ class CacheService: return CrudResponseModel(is_success=True, message=f'{cache_key}清除成功') @classmethod - async def clear_cache_monitor_all_services(cls, request: Request): + async def clear_cache_monitor_all_services(cls, request: Request) -> CrudResponseModel: """ 清除所有缓存service diff --git a/ruoyi-fastapi-backend/module_admin/service/captcha_service.py b/ruoyi-fastapi-backend/module_admin/service/captcha_service.py index 1be8ffb..5187d74 100644 --- a/ruoyi-fastapi-backend/module_admin/service/captcha_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/captcha_service.py @@ -2,6 +2,7 @@ import base64 import io import os import random + from PIL import Image, ImageDraw, ImageFont @@ -11,7 +12,7 @@ class CaptchaService: """ @classmethod - async def create_captcha_image_service(cls): + async def create_captcha_image_service(cls) -> list[str, int]: # 创建空白图像 image = Image.new('RGB', (160, 60), color='#EAEAEA') diff --git a/ruoyi-fastapi-backend/module_admin/service/common_service.py b/ruoyi-fastapi-backend/module_admin/service/common_service.py index 20eb868..b5832ad 100644 --- a/ruoyi-fastapi-backend/module_admin/service/common_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/common_service.py @@ -1,6 +1,9 @@ import os from datetime import datetime + +import aiofiles from fastapi import BackgroundTasks, Request, UploadFile + from config.env import UploadConfig from exceptions.exception import ServiceException from module_admin.entity.vo.common_vo import CrudResponseModel, UploadResponseModel @@ -13,7 +16,7 @@ class CommonService: """ @classmethod - async def upload_service(cls, request: Request, file: UploadFile): + async def upload_service(cls, request: Request, file: UploadFile) -> CrudResponseModel: """ 通用上传service @@ -23,33 +26,39 @@ class CommonService: """ if not UploadUtil.check_file_extension(file): raise ServiceException(message='文件类型不合法') - else: - relative_path = f'upload/{datetime.now().strftime("%Y")}/{datetime.now().strftime("%m")}/{datetime.now().strftime("%d")}' - dir_path = os.path.join(UploadConfig.UPLOAD_PATH, relative_path) - try: - os.makedirs(dir_path) - except FileExistsError: - pass - filename = f'{file.filename.rsplit(".", 1)[0]}_{datetime.now().strftime("%Y%m%d%H%M%S")}{UploadConfig.UPLOAD_MACHINE}{UploadUtil.generate_random_number()}.{file.filename.rsplit(".")[-1]}' - filepath = os.path.join(dir_path, filename) - with open(filepath, 'wb') as f: - # 流式写出大型文件,这里的10代表10MB - for chunk in iter(lambda: file.file.read(1024 * 1024 * 10), b''): - f.write(chunk) + relative_path = ( + f'upload/{datetime.now().strftime("%Y")}/{datetime.now().strftime("%m")}/{datetime.now().strftime("%d")}' + ) + dir_path = os.path.join(UploadConfig.UPLOAD_PATH, relative_path) + try: + os.makedirs(dir_path) + except FileExistsError: + pass + filename = f'{file.filename.rsplit(".", 1)[0]}_{datetime.now().strftime("%Y%m%d%H%M%S")}{UploadConfig.UPLOAD_MACHINE}{UploadUtil.generate_random_number()}.{file.filename.rsplit(".")[-1]}' + filepath = os.path.join(dir_path, filename) + async with aiofiles.open(filepath, 'wb') as f: + # 流式写出大型文件,这里的10代表10MB + while True: + chunk = await file.read(1024 * 1024 * 10) + if not chunk: + break + await f.write(chunk) - return CrudResponseModel( - is_success=True, - result=UploadResponseModel( - fileName=f'{UploadConfig.UPLOAD_PREFIX}/{relative_path}/{filename}', - newFileName=filename, - originalFilename=file.filename, - url=f'{request.base_url}{UploadConfig.UPLOAD_PREFIX[1:]}/{relative_path}/{filename}', - ), - message='上传成功', - ) + return CrudResponseModel( + is_success=True, + result=UploadResponseModel( + fileName=f'{UploadConfig.UPLOAD_PREFIX}/{relative_path}/{filename}', + newFileName=filename, + originalFilename=file.filename, + url=f'{request.base_url}{UploadConfig.UPLOAD_PREFIX[1:]}/{relative_path}/{filename}', + ), + message='上传成功', + ) @classmethod - async def download_services(cls, background_tasks: BackgroundTasks, file_name, delete: bool): + async def download_services( + cls, background_tasks: BackgroundTasks, file_name: str, delete: bool + ) -> CrudResponseModel: """ 下载下载目录文件service @@ -61,15 +70,14 @@ class CommonService: filepath = os.path.join(UploadConfig.DOWNLOAD_PATH, file_name) if '..' in file_name: raise ServiceException(message='文件名称不合法') - elif not UploadUtil.check_file_exists(filepath): + if not UploadUtil.check_file_exists(filepath): raise ServiceException(message='文件不存在') - else: - if delete: - background_tasks.add_task(UploadUtil.delete_file, filepath) - return CrudResponseModel(is_success=True, result=UploadUtil.generate_file(filepath), message='下载成功') + if delete: + background_tasks.add_task(UploadUtil.delete_file, filepath) + return CrudResponseModel(is_success=True, result=UploadUtil.generate_file(filepath), message='下载成功') @classmethod - async def download_resource_services(cls, resource: str): + async def download_resource_services(cls, resource: str) -> CrudResponseModel: """ 下载上传目录文件service @@ -85,7 +93,6 @@ class CommonService: or not UploadUtil.check_file_random_code(filename) ): raise ServiceException(message='文件名称不合法') - elif not UploadUtil.check_file_exists(filepath): + if not UploadUtil.check_file_exists(filepath): raise ServiceException(message='文件不存在') - else: - return CrudResponseModel(is_success=True, result=UploadUtil.generate_file(filepath), message='下载成功') + return CrudResponseModel(is_success=True, result=UploadUtil.generate_file(filepath), message='下载成功') diff --git a/ruoyi-fastapi-backend/module_admin/service/config_service.py b/ruoyi-fastapi-backend/module_admin/service/config_service.py index 312006d..20a4968 100644 --- a/ruoyi-fastapi-backend/module_admin/service/config_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/config_service.py @@ -1,6 +1,9 @@ +from typing import Any, Union + from fastapi import Request +from redis import asyncio as aioredis from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.constant import CommonConstant from config.enums import RedisInitKeyConfig from exceptions.exception import ServiceException @@ -9,6 +12,7 @@ from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel class ConfigService: @@ -19,7 +23,7 @@ class ConfigService: @classmethod async def get_config_list_services( cls, query_db: AsyncSession, query_object: ConfigPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取参数配置列表信息service @@ -33,7 +37,7 @@ class ConfigService: return config_list_result @classmethod - async def init_cache_sys_config_services(cls, query_db: AsyncSession, redis): + async def init_cache_sys_config_services(cls, query_db: AsyncSession, redis: aioredis.Redis) -> None: """ 应用初始化:获取所有参数配置对应的键值对信息并缓存service @@ -46,15 +50,15 @@ class ConfigService: # 删除匹配的键 if keys: await redis.delete(*keys) - config_all = await ConfigDao.get_config_list(query_db, ConfigPageQueryModel(**dict()), is_page=False) + config_all = await ConfigDao.get_config_list(query_db, ConfigPageQueryModel(), is_page=False) for config_obj in config_all: await redis.set( - f"{RedisInitKeyConfig.SYS_CONFIG.key}:{config_obj.get('configKey')}", + f'{RedisInitKeyConfig.SYS_CONFIG.key}:{config_obj.get("configKey")}', config_obj.get('configValue'), ) @classmethod - async def query_config_list_from_cache_services(cls, redis, config_key: str): + async def query_config_list_from_cache_services(cls, redis: aioredis.Redis, config_key: str) -> Any: """ 从缓存获取参数键名对应值service @@ -67,7 +71,7 @@ class ConfigService: return result @classmethod - async def check_config_key_unique_services(cls, query_db: AsyncSession, page_object: ConfigModel): + async def check_config_key_unique_services(cls, query_db: AsyncSession, page_object: ConfigModel) -> bool: """ 校验参数键名是否唯一service @@ -82,7 +86,9 @@ class ConfigService: return CommonConstant.UNIQUE @classmethod - async def add_config_services(cls, request: Request, query_db: AsyncSession, page_object: ConfigModel): + async def add_config_services( + cls, request: Request, query_db: AsyncSession, page_object: ConfigModel + ) -> CrudResponseModel: """ 新增参数配置信息service @@ -93,20 +99,21 @@ class ConfigService: """ if not await cls.check_config_key_unique_services(query_db, page_object): raise ServiceException(message=f'新增参数{page_object.config_name}失败,参数键名已存在') - else: - try: - await ConfigDao.add_config_dao(query_db, page_object) - await query_db.commit() - await request.app.state.redis.set( - f'{RedisInitKeyConfig.SYS_CONFIG.key}:{page_object.config_key}', page_object.config_value - ) - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await ConfigDao.add_config_dao(query_db, page_object) + await query_db.commit() + await request.app.state.redis.set( + f'{RedisInitKeyConfig.SYS_CONFIG.key}:{page_object.config_key}', page_object.config_value + ) + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_config_services(cls, request: Request, query_db: AsyncSession, page_object: ConfigModel): + async def edit_config_services( + cls, request: Request, query_db: AsyncSession, page_object: ConfigModel + ) -> CrudResponseModel: """ 编辑参数配置信息service @@ -120,26 +127,27 @@ class ConfigService: if config_info.config_id: if not await cls.check_config_key_unique_services(query_db, page_object): raise ServiceException(message=f'修改参数{page_object.config_name}失败,参数键名已存在') - else: - try: - await ConfigDao.edit_config_dao(query_db, edit_config) - await query_db.commit() - if config_info.config_key != page_object.config_key: - await request.app.state.redis.delete( - f'{RedisInitKeyConfig.SYS_CONFIG.key}:{config_info.config_key}' - ) - await request.app.state.redis.set( - f'{RedisInitKeyConfig.SYS_CONFIG.key}:{page_object.config_key}', page_object.config_value + try: + await ConfigDao.edit_config_dao(query_db, edit_config) + await query_db.commit() + if config_info.config_key != page_object.config_key: + await request.app.state.redis.delete( + f'{RedisInitKeyConfig.SYS_CONFIG.key}:{config_info.config_key}' ) - return CrudResponseModel(is_success=True, message='更新成功') - except Exception as e: - await query_db.rollback() - raise e + await request.app.state.redis.set( + f'{RedisInitKeyConfig.SYS_CONFIG.key}:{page_object.config_key}', page_object.config_value + ) + return CrudResponseModel(is_success=True, message='更新成功') + except Exception as e: + await query_db.rollback() + raise e else: raise ServiceException(message='参数配置不存在') @classmethod - async def delete_config_services(cls, request: Request, query_db: AsyncSession, page_object: DeleteConfigModel): + async def delete_config_services( + cls, request: Request, query_db: AsyncSession, page_object: DeleteConfigModel + ) -> CrudResponseModel: """ 删除参数配置信息service @@ -156,9 +164,8 @@ class ConfigService: config_info = await cls.config_detail_services(query_db, int(config_id)) if config_info.config_type == CommonConstant.YES: raise ServiceException(message=f'内置参数{config_info.config_key}不能删除') - else: - await ConfigDao.delete_config_dao(query_db, ConfigModel(configId=int(config_id))) - delete_config_key_list.append(f'{RedisInitKeyConfig.SYS_CONFIG.key}:{config_info.config_key}') + await ConfigDao.delete_config_dao(query_db, ConfigModel(configId=int(config_id))) + delete_config_key_list.append(f'{RedisInitKeyConfig.SYS_CONFIG.key}:{config_info.config_key}') await query_db.commit() if delete_config_key_list: await request.app.state.redis.delete(*delete_config_key_list) @@ -170,7 +177,7 @@ class ConfigService: raise ServiceException(message='传入参数配置id为空') @classmethod - async def config_detail_services(cls, query_db: AsyncSession, config_id: int): + async def config_detail_services(cls, query_db: AsyncSession, config_id: int) -> ConfigModel: """ 获取参数配置详细信息service @@ -179,15 +186,12 @@ class ConfigService: :return: 参数配置id对应的信息 """ config = await ConfigDao.get_config_detail_by_id(query_db, config_id=config_id) - if config: - result = ConfigModel(**CamelCaseUtil.transform_result(config)) - else: - result = ConfigModel(**dict()) + result = ConfigModel(**CamelCaseUtil.transform_result(config)) if config else ConfigModel() return result @staticmethod - async def export_config_list_services(config_list: List): + async def export_config_list_services(config_list: list) -> bytes: """ 导出参数配置信息service @@ -218,7 +222,7 @@ class ConfigService: return binary_data @classmethod - async def refresh_sys_config_services(cls, request: Request, query_db: AsyncSession): + async def refresh_sys_config_services(cls, request: Request, query_db: AsyncSession) -> CrudResponseModel: """ 刷新字典缓存信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/dept_service.py b/ruoyi-fastapi-backend/module_admin/service/dept_service.py index 50594c8..247ee6b 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dept_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dept_service.py @@ -1,7 +1,12 @@ +from collections.abc import Sequence +from typing import Any + from sqlalchemy.ext.asyncio import AsyncSession + from config.constant import CommonConstant from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.dept_dao import DeptDao +from module_admin.entity.do.dept_do import SysDept from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel from utils.common_util import CamelCaseUtil @@ -13,7 +18,9 @@ class DeptService: """ @classmethod - async def get_dept_tree_services(cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str): + async def get_dept_tree_services( + cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str + ) -> list[dict[str, Any]]: """ 获取部门树信息service @@ -30,7 +37,7 @@ class DeptService: @classmethod async def get_dept_for_edit_option_services( cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str - ): + ) -> list[dict[str, Any]]: """ 获取部门编辑部门树信息service @@ -44,7 +51,9 @@ class DeptService: return CamelCaseUtil.transform_result(dept_list_result) @classmethod - async def get_dept_list_services(cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str): + async def get_dept_list_services( + cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str + ) -> list[dict[str, Any]]: """ 获取部门列表信息service @@ -58,7 +67,9 @@ class DeptService: return CamelCaseUtil.transform_result(dept_list_result) @classmethod - async def check_dept_data_scope_services(cls, query_db: AsyncSession, dept_id: int, data_scope_sql: str): + async def check_dept_data_scope_services( + cls, query_db: AsyncSession, dept_id: int, data_scope_sql: str + ) -> CrudResponseModel: """ 校验部门是否有数据权限service @@ -70,11 +81,10 @@ class DeptService: depts = await DeptDao.get_dept_list(query_db, DeptModel(deptId=dept_id), data_scope_sql) if depts: return CrudResponseModel(is_success=True, message='校验通过') - else: - raise ServiceException(message='没有权限访问部门数据') + raise ServiceException(message='没有权限访问部门数据') @classmethod - async def check_dept_name_unique_services(cls, query_db: AsyncSession, page_object: DeptModel): + async def check_dept_name_unique_services(cls, query_db: AsyncSession, page_object: DeptModel) -> bool: """ 校验部门名称是否唯一service @@ -91,7 +101,7 @@ class DeptService: return CommonConstant.UNIQUE @classmethod - async def add_dept_services(cls, query_db: AsyncSession, page_object: DeptModel): + async def add_dept_services(cls, query_db: AsyncSession, page_object: DeptModel) -> CrudResponseModel: """ 新增部门信息service @@ -114,7 +124,7 @@ class DeptService: raise e @classmethod - async def edit_dept_services(cls, query_db: AsyncSession, page_object: DeptModel): + async def edit_dept_services(cls, query_db: AsyncSession, page_object: DeptModel) -> CrudResponseModel: """ 编辑部门信息service @@ -124,9 +134,9 @@ class DeptService: """ if not await cls.check_dept_name_unique_services(query_db, page_object): raise ServiceException(message=f'修改部门{page_object.dept_name}失败,部门名称已存在') - elif page_object.dept_id == page_object.parent_id: + if page_object.dept_id == page_object.parent_id: raise ServiceException(message=f'修改部门{page_object.dept_name}失败,上级部门不能是自己') - elif ( + if ( page_object.status == CommonConstant.DEPT_DISABLE and (await DeptDao.count_normal_children_dept_dao(query_db, page_object.dept_id)) > 0 ): @@ -154,7 +164,7 @@ class DeptService: raise e @classmethod - async def delete_dept_services(cls, query_db: AsyncSession, page_object: DeleteDeptModel): + async def delete_dept_services(cls, query_db: AsyncSession, page_object: DeleteDeptModel) -> CrudResponseModel: """ 删除部门信息service @@ -168,7 +178,7 @@ class DeptService: for dept_id in dept_id_list: if (await DeptDao.count_children_dept_dao(query_db, int(dept_id))) > 0: raise ServiceWarning(message='存在下级部门,不允许删除') - elif (await DeptDao.count_dept_user_dao(query_db, int(dept_id))) > 0: + if (await DeptDao.count_dept_user_dao(query_db, int(dept_id))) > 0: raise ServiceWarning(message='部门存在用户,不允许删除') await DeptDao.delete_dept_dao(query_db, DeptModel(deptId=dept_id)) @@ -181,7 +191,7 @@ class DeptService: raise ServiceException(message='传入部门id为空') @classmethod - async def dept_detail_services(cls, query_db: AsyncSession, dept_id: int): + async def dept_detail_services(cls, query_db: AsyncSession, dept_id: int) -> DeptModel: """ 获取部门详细信息service @@ -190,37 +200,34 @@ class DeptService: :return: 部门id对应的信息 """ dept = await DeptDao.get_dept_detail_by_id(query_db, dept_id=dept_id) - if dept: - result = DeptModel(**CamelCaseUtil.transform_result(dept)) - else: - result = DeptModel(**dict()) + result = DeptModel(**CamelCaseUtil.transform_result(dept)) if dept else DeptModel() return result @classmethod - def list_to_tree(cls, permission_list: list) -> list: + def list_to_tree(cls, permission_list: Sequence[SysDept]) -> list[dict[str, Any]]: """ 工具方法:根据部门列表信息生成树形嵌套数据 :param permission_list: 部门列表信息 :return: 部门树形嵌套数据 """ - permission_list = [ - dict(id=item.dept_id, label=item.dept_name, parentId=item.parent_id) for item in permission_list + _permission_list = [ + {'id': item.dept_id, 'label': item.dept_name, 'parentId': item.parent_id} for item in permission_list ] # 转成id为key的字典 - mapping: dict = dict(zip([i['id'] for i in permission_list], permission_list)) + mapping: dict[int, dict[str, Any]] = dict(zip([i['id'] for i in _permission_list], _permission_list)) # 树容器 - container: list = [] + container: list[dict[str, Any]] = [] - for d in permission_list: + for d in _permission_list: # 如果找不到父级项,则是根节点 - parent: dict = mapping.get(d['parentId']) + parent = mapping.get(d['parentId']) if parent is None: container.append(d) else: - children: list = parent.get('children') + children: list[dict[str, Any]] = parent.get('children') if not children: children = [] children.append(d) @@ -229,7 +236,7 @@ class DeptService: return container @classmethod - async def replace_first(cls, original_str: str, old_str: str, new_str: str): + async def replace_first(cls, original_str: str, old_str: str, new_str: str) -> str: """ 工具方法:替换字符串 @@ -240,11 +247,10 @@ class DeptService: """ if original_str.startswith(old_str): return original_str.replace(old_str, new_str, 1) - else: - return original_str + return original_str @classmethod - async def update_parent_dept_status_normal(cls, query_db: AsyncSession, dept: DeptModel): + async def update_parent_dept_status_normal(cls, query_db: AsyncSession, dept: DeptModel) -> None: """ 更新父部门状态为正常 @@ -256,7 +262,9 @@ class DeptService: await DeptDao.update_dept_status_normal_dao(query_db, list(map(int, dept_id_list))) @classmethod - async def update_dept_children(cls, query_db: AsyncSession, dept_id: int, new_ancestors: str, old_ancestors: str): + async def update_dept_children( + cls, query_db: AsyncSession, dept_id: int, new_ancestors: str, old_ancestors: str + ) -> None: """ 更新子部门信息 diff --git a/ruoyi-fastapi-backend/module_admin/service/dict_service.py b/ruoyi-fastapi-backend/module_admin/service/dict_service.py index 0acfd73..9bd556e 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dict_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dict_service.py @@ -1,11 +1,16 @@ import json +from collections.abc import Sequence +from typing import Any, Union + from fastapi import Request +from redis import asyncio as aioredis from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.constant import CommonConstant from config.enums import RedisInitKeyConfig from exceptions.exception import ServiceException from module_admin.dao.dict_dao import DictDataDao, DictTypeDao +from module_admin.entity.do.dict_do import SysDictData from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.dict_vo import ( DeleteDictDataModel, @@ -17,6 +22,7 @@ from module_admin.entity.vo.dict_vo import ( ) from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel class DictTypeService: @@ -27,7 +33,7 @@ class DictTypeService: @classmethod async def get_dict_type_list_services( cls, query_db: AsyncSession, query_object: DictTypePageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取字典类型列表信息service @@ -41,7 +47,7 @@ class DictTypeService: return dict_type_list_result @classmethod - async def check_dict_type_unique_services(cls, query_db: AsyncSession, page_object: DictTypeModel): + async def check_dict_type_unique_services(cls, query_db: AsyncSession, page_object: DictTypeModel) -> bool: """ 校验字典类型称是否唯一service @@ -58,7 +64,9 @@ class DictTypeService: return CommonConstant.UNIQUE @classmethod - async def add_dict_type_services(cls, request: Request, query_db: AsyncSession, page_object: DictTypeModel): + async def add_dict_type_services( + cls, request: Request, query_db: AsyncSession, page_object: DictTypeModel + ) -> CrudResponseModel: """ 新增字典类型信息service @@ -69,20 +77,21 @@ class DictTypeService: """ if not await cls.check_dict_type_unique_services(query_db, page_object): raise ServiceException(message=f'新增字典{page_object.dict_name}失败,字典类型已存在') - else: - try: - await DictTypeDao.add_dict_type_dao(query_db, page_object) - await query_db.commit() - await request.app.state.redis.set(f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', '') - result = dict(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await DictTypeDao.add_dict_type_dao(query_db, page_object) + await query_db.commit() + await request.app.state.redis.set(f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', '') + result = {'is_success': True, 'message': '新增成功'} + except Exception as e: + await query_db.rollback() + raise e return CrudResponseModel(**result) @classmethod - async def edit_dict_type_services(cls, request: Request, query_db: AsyncSession, page_object: DictTypeModel): + async def edit_dict_type_services( + cls, request: Request, query_db: AsyncSession, page_object: DictTypeModel + ) -> CrudResponseModel: """ 编辑字典类型信息service @@ -96,38 +105,37 @@ class DictTypeService: if dict_type_info.dict_id: if not await cls.check_dict_type_unique_services(query_db, page_object): raise ServiceException(message=f'修改字典{page_object.dict_name}失败,字典类型已存在') - else: - try: - query_dict_data = DictDataPageQueryModel(dictType=dict_type_info.dict_type) - dict_data_list = await DictDataDao.get_dict_data_list(query_db, query_dict_data, is_page=False) - if dict_type_info.dict_type != page_object.dict_type: - for dict_data in dict_data_list: - edit_dict_data = DictDataModel( - dictCode=dict_data.get('dict_code'), - dictType=page_object.dict_type, - updateBy=page_object.update_by, - updateTime=page_object.update_time, - ).model_dump(exclude_unset=True) - await DictDataDao.edit_dict_data_dao(query_db, edit_dict_data) - await DictTypeDao.edit_dict_type_dao(query_db, edit_dict_type) - await query_db.commit() - if dict_type_info.dict_type != page_object.dict_type: - dict_data = [CamelCaseUtil.transform_result(row) for row in dict_data_list if row] - await request.app.state.redis.set( - f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', - json.dumps(dict_data, ensure_ascii=False, default=str), - ) - return CrudResponseModel(is_success=True, message='更新成功') - except Exception as e: - await query_db.rollback() - raise e + try: + query_dict_data = DictDataPageQueryModel(dictType=dict_type_info.dict_type) + dict_data_list = await DictDataDao.get_dict_data_list(query_db, query_dict_data, is_page=False) + if dict_type_info.dict_type != page_object.dict_type: + for dict_data in dict_data_list: + edit_dict_data = DictDataModel( + dictCode=dict_data.get('dict_code'), + dictType=page_object.dict_type, + updateBy=page_object.update_by, + updateTime=page_object.update_time, + ).model_dump(exclude_unset=True) + await DictDataDao.edit_dict_data_dao(query_db, edit_dict_data) + await DictTypeDao.edit_dict_type_dao(query_db, edit_dict_type) + await query_db.commit() + if dict_type_info.dict_type != page_object.dict_type: + dict_data = [CamelCaseUtil.transform_result(row) for row in dict_data_list if row] + await request.app.state.redis.set( + f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', + json.dumps(dict_data, ensure_ascii=False, default=str), + ) + return CrudResponseModel(is_success=True, message='更新成功') + except Exception as e: + await query_db.rollback() + raise e else: raise ServiceException(message='字典类型不存在') @classmethod async def delete_dict_type_services( cls, request: Request, query_db: AsyncSession, page_object: DeleteDictTypeModel - ): + ) -> CrudResponseModel: """ 删除字典类型信息service @@ -157,7 +165,7 @@ class DictTypeService: raise ServiceException(message='传入字典类型id为空') @classmethod - async def dict_type_detail_services(cls, query_db: AsyncSession, dict_id: int): + async def dict_type_detail_services(cls, query_db: AsyncSession, dict_id: int) -> DictTypeModel: """ 获取字典类型详细信息service @@ -166,15 +174,12 @@ class DictTypeService: :return: 字典类型id对应的信息 """ dict_type = await DictTypeDao.get_dict_type_detail_by_id(query_db, dict_id=dict_id) - if dict_type: - result = DictTypeModel(**CamelCaseUtil.transform_result(dict_type)) - else: - result = DictTypeModel(**dict()) + result = DictTypeModel(**CamelCaseUtil.transform_result(dict_type)) if dict_type else DictTypeModel() return result @staticmethod - async def export_dict_type_list_services(dict_type_list: List): + async def export_dict_type_list_services(dict_type_list: list) -> bytes: """ 导出字典类型信息service @@ -204,7 +209,7 @@ class DictTypeService: return binary_data @classmethod - async def refresh_sys_dict_services(cls, request: Request, query_db: AsyncSession): + async def refresh_sys_dict_services(cls, request: Request, query_db: AsyncSession) -> CrudResponseModel: """ 刷新字典缓存信息service @@ -213,7 +218,7 @@ class DictTypeService: :return: 刷新字典缓存校验结果 """ await DictDataService.init_cache_sys_dict_services(query_db, request.app.state.redis) - result = dict(is_success=True, message='刷新成功') + result = {'is_success': True, 'message': '刷新成功'} return CrudResponseModel(**result) @@ -226,7 +231,7 @@ class DictDataService: @classmethod async def get_dict_data_list_services( cls, query_db: AsyncSession, query_object: DictDataPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取字典数据列表信息service @@ -240,7 +245,7 @@ class DictDataService: return dict_data_list_result @classmethod - async def query_dict_data_list_services(cls, query_db: AsyncSession, dict_type: str): + async def query_dict_data_list_services(cls, query_db: AsyncSession, dict_type: str) -> Sequence[SysDictData]: """ 获取字典数据列表信息service @@ -253,7 +258,7 @@ class DictDataService: return dict_data_list_result @classmethod - async def init_cache_sys_dict_services(cls, query_db: AsyncSession, redis): + async def init_cache_sys_dict_services(cls, query_db: AsyncSession, redis: aioredis.Redis) -> None: """ 应用初始化:获取所有字典类型对应的字典数据信息并缓存service @@ -277,7 +282,9 @@ class DictDataService: ) @classmethod - async def query_dict_data_list_from_cache_services(cls, redis, dict_type: str): + async def query_dict_data_list_from_cache_services( + cls, redis: aioredis.Redis, dict_type: str + ) -> list[dict[str, Any]]: """ 从缓存获取字典数据列表信息service @@ -293,7 +300,7 @@ class DictDataService: return CamelCaseUtil.transform_result(result) @classmethod - async def check_dict_data_unique_services(cls, query_db: AsyncSession, page_object: DictDataModel): + async def check_dict_data_unique_services(cls, query_db: AsyncSession, page_object: DictDataModel) -> bool: """ 校验字典数据是否唯一service @@ -308,7 +315,9 @@ class DictDataService: return CommonConstant.UNIQUE @classmethod - async def add_dict_data_services(cls, request: Request, query_db: AsyncSession, page_object: DictDataModel): + async def add_dict_data_services( + cls, request: Request, query_db: AsyncSession, page_object: DictDataModel + ) -> CrudResponseModel: """ 新增字典数据信息service @@ -321,22 +330,23 @@ class DictDataService: raise ServiceException( message=f'新增字典数据{page_object.dict_label}失败,{page_object.dict_type}下已存在该字典数据' ) - else: - try: - await DictDataDao.add_dict_data_dao(query_db, page_object) - await query_db.commit() - dict_data_list = await cls.query_dict_data_list_services(query_db, page_object.dict_type) - await request.app.state.redis.set( - f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', - json.dumps(CamelCaseUtil.transform_result(dict_data_list), ensure_ascii=False, default=str), - ) - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await DictDataDao.add_dict_data_dao(query_db, page_object) + await query_db.commit() + dict_data_list = await cls.query_dict_data_list_services(query_db, page_object.dict_type) + await request.app.state.redis.set( + f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', + json.dumps(CamelCaseUtil.transform_result(dict_data_list), ensure_ascii=False, default=str), + ) + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_dict_data_services(cls, request: Request, query_db: AsyncSession, page_object: DictDataModel): + async def edit_dict_data_services( + cls, request: Request, query_db: AsyncSession, page_object: DictDataModel + ) -> CrudResponseModel: """ 编辑字典数据信息service @@ -352,26 +362,25 @@ class DictDataService: raise ServiceException( message=f'新增字典数据{page_object.dict_label}失败,{page_object.dict_type}下已存在该字典数据' ) - else: - try: - await DictDataDao.edit_dict_data_dao(query_db, edit_data_type) - await query_db.commit() - dict_data_list = await cls.query_dict_data_list_services(query_db, page_object.dict_type) - await request.app.state.redis.set( - f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', - json.dumps(CamelCaseUtil.transform_result(dict_data_list), ensure_ascii=False, default=str), - ) - return CrudResponseModel(is_success=True, message='更新成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await DictDataDao.edit_dict_data_dao(query_db, edit_data_type) + await query_db.commit() + dict_data_list = await cls.query_dict_data_list_services(query_db, page_object.dict_type) + await request.app.state.redis.set( + f'{RedisInitKeyConfig.SYS_DICT.key}:{page_object.dict_type}', + json.dumps(CamelCaseUtil.transform_result(dict_data_list), ensure_ascii=False, default=str), + ) + return CrudResponseModel(is_success=True, message='更新成功') + except Exception as e: + await query_db.rollback() + raise e else: raise ServiceException(message='字典数据不存在') @classmethod async def delete_dict_data_services( cls, request: Request, query_db: AsyncSession, page_object: DeleteDictDataModel - ): + ) -> CrudResponseModel: """ 删除字典数据信息service @@ -403,7 +412,7 @@ class DictDataService: raise ServiceException(message='传入字典数据id为空') @classmethod - async def dict_data_detail_services(cls, query_db: AsyncSession, dict_code: int): + async def dict_data_detail_services(cls, query_db: AsyncSession, dict_code: int) -> DictDataModel: """ 获取字典数据详细信息service @@ -412,15 +421,12 @@ class DictDataService: :return: 字典数据id对应的信息 """ dict_data = await DictDataDao.get_dict_data_detail_by_id(query_db, dict_code=dict_code) - if dict_data: - result = DictDataModel(**CamelCaseUtil.transform_result(dict_data)) - else: - result = DictDataModel(**dict()) + result = DictDataModel(**CamelCaseUtil.transform_result(dict_data)) if dict_data else DictDataModel() return result @staticmethod - async def export_dict_data_list_services(dict_data_list: List): + async def export_dict_data_list_services(dict_data_list: list) -> bytes: """ 导出字典数据信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/job_log_service.py b/ruoyi-fastapi-backend/module_admin/service/job_log_service.py index 596abe7..be67b3b 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_log_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_log_service.py @@ -1,12 +1,15 @@ +from typing import Any, Union + from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session -from typing import List + from module_admin.dao.job_log_dao import JobLogDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.job_vo import DeleteJobLogModel, JobLogModel, JobLogPageQueryModel from module_admin.service.dict_service import DictDataService from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel class JobLogService: @@ -17,7 +20,7 @@ class JobLogService: @classmethod async def get_job_log_list_services( cls, query_db: AsyncSession, query_object: JobLogPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取定时任务日志列表信息service @@ -31,7 +34,7 @@ class JobLogService: return job_log_list_result @classmethod - def add_job_log_services(cls, query_db: Session, page_object: JobLogModel): + def add_job_log_services(cls, query_db: Session, page_object: JobLogModel) -> CrudResponseModel: """ 新增定时任务日志信息service @@ -42,15 +45,15 @@ class JobLogService: try: JobLogDao.add_job_log_dao(query_db, page_object) query_db.commit() - result = dict(is_success=True, message='新增成功') + result = {'is_success': True, 'message': '新增成功'} except Exception as e: query_db.rollback() - result = dict(is_success=False, message=str(e)) + result = {'is_success': False, 'message': str(e)} return CrudResponseModel(**result) @classmethod - async def delete_job_log_services(cls, query_db: AsyncSession, page_object: DeleteJobLogModel): + async def delete_job_log_services(cls, query_db: AsyncSession, page_object: DeleteJobLogModel) -> CrudResponseModel: """ 删除定时任务日志信息service @@ -64,16 +67,16 @@ class JobLogService: for job_log_id in job_log_id_list: await JobLogDao.delete_job_log_dao(query_db, JobLogModel(jobLogId=job_log_id)) await query_db.commit() - result = dict(is_success=True, message='删除成功') + result = {'is_success': True, 'message': '删除成功'} except Exception as e: await query_db.rollback() raise e else: - result = dict(is_success=False, message='传入定时任务日志id为空') + result = {'is_success': False, 'message': '传入定时任务日志id为空'} return CrudResponseModel(**result) @classmethod - async def clear_job_log_services(cls, query_db: AsyncSession): + async def clear_job_log_services(cls, query_db: AsyncSession) -> CrudResponseModel: """ 清除定时任务日志信息service @@ -83,7 +86,7 @@ class JobLogService: try: await JobLogDao.clear_job_log_dao(query_db) await query_db.commit() - result = dict(is_success=True, message='清除成功') + result = {'is_success': True, 'message': '清除成功'} except Exception as e: await query_db.rollback() raise e @@ -91,7 +94,7 @@ class JobLogService: return CrudResponseModel(**result) @staticmethod - async def export_job_log_list_services(request: Request, job_log_list: List): + async def export_job_log_list_services(request: Request, job_log_list: list) -> bytes: """ 导出定时任务日志信息service @@ -118,13 +121,13 @@ class JobLogService: job_group_list = await DictDataService.query_dict_data_list_from_cache_services( request.app.state.redis, dict_type='sys_job_group' ) - job_group_option = [dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in job_group_list] + job_group_option = [{'label': item.get('dictLabel'), 'value': item.get('dictValue')} for item in job_group_list] job_group_option_dict = {item.get('value'): item for item in job_group_option} job_executor_list = await DictDataService.query_dict_data_list_from_cache_services( request.app.state.redis, dict_type='sys_job_executor' ) job_executor_option = [ - dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in job_executor_list + {'label': item.get('dictLabel'), 'value': item.get('dictValue')} for item in job_executor_list ] job_executor_option_dict = {item.get('value'): item for item in job_executor_option} @@ -133,9 +136,9 @@ class JobLogService: item['status'] = '正常' else: item['status'] = '暂停' - if str(item.get('jobGroup')) in job_group_option_dict.keys(): + if str(item.get('jobGroup')) in job_group_option_dict: item['jobGroup'] = job_group_option_dict.get(str(item.get('jobGroup'))).get('label') - if str(item.get('jobExecutor')) in job_executor_option_dict.keys(): + if str(item.get('jobExecutor')) in job_executor_option_dict: item['jobExecutor'] = job_executor_option_dict.get(str(item.get('jobExecutor'))).get('label') binary_data = ExcelUtil.export_list2excel(job_log_list, mapping_dict) diff --git a/ruoyi-fastapi-backend/module_admin/service/job_service.py b/ruoyi-fastapi-backend/module_admin/service/job_service.py index 2b783f0..7e584ce 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_service.py @@ -1,6 +1,8 @@ +from typing import Any, Union + from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.constant import CommonConstant, JobConstant from config.get_scheduler import SchedulerUtil from exceptions.exception import ServiceException @@ -11,6 +13,7 @@ from module_admin.service.dict_service import DictDataService from utils.common_util import CamelCaseUtil from utils.cron_util import CronUtil from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel from utils.string_util import StringUtil @@ -22,7 +25,7 @@ class JobService: @classmethod async def get_job_list_services( cls, query_db: AsyncSession, query_object: JobPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取定时任务列表信息service @@ -36,7 +39,7 @@ class JobService: return job_list_result @classmethod - async def check_job_unique_services(cls, query_db: AsyncSession, page_object: JobModel): + async def check_job_unique_services(cls, query_db: AsyncSession, page_object: JobModel) -> bool: """ 校验定时任务是否存在service @@ -51,7 +54,7 @@ class JobService: return CommonConstant.UNIQUE @classmethod - async def add_job_services(cls, query_db: AsyncSession, page_object: JobModel): + async def add_job_services(cls, query_db: AsyncSession, page_object: JobModel) -> CrudResponseModel: """ 新增定时任务信息service @@ -61,38 +64,46 @@ class JobService: """ if not CronUtil.validate_cron_expression(page_object.cron_expression): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,Cron表达式不正确') - elif StringUtil.contains_ignore_case(page_object.invoke_target, CommonConstant.LOOKUP_RMI): + if StringUtil.contains_ignore_case(page_object.invoke_target, CommonConstant.LOOKUP_RMI): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,目标字符串不允许rmi调用') - elif StringUtil.contains_any_ignore_case( + if StringUtil.contains_any_ignore_case( page_object.invoke_target, [CommonConstant.LOOKUP_LDAP, CommonConstant.LOOKUP_LDAPS] ): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,目标字符串不允许ldap(s)调用') - elif StringUtil.contains_any_ignore_case( - page_object.invoke_target, [CommonConstant.HTTP, CommonConstant.HTTPS] - ): + if StringUtil.contains_any_ignore_case(page_object.invoke_target, [CommonConstant.HTTP, CommonConstant.HTTPS]): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,目标字符串不允许http(s)调用') - elif StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_ERROR_LIST): + if StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_ERROR_LIST): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,目标字符串存在违规') - elif not StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_WHITE_LIST): + if not StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_WHITE_LIST): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,目标字符串不在白名单内') - elif not await cls.check_job_unique_services(query_db, page_object): + if not await cls.check_job_unique_services(query_db, page_object): raise ServiceException(message=f'新增定时任务{page_object.job_name}失败,定时任务已存在') - else: - try: - add_job = await JobDao.add_job_dao(query_db, page_object) - job_info = await cls.job_detail_services(query_db, add_job.job_id) - if job_info.status == '0': - SchedulerUtil.add_scheduler_job(job_info=job_info) - await query_db.commit() - result = dict(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + add_job = await JobDao.add_job_dao(query_db, page_object) + job_info = await cls.job_detail_services(query_db, add_job.job_id) + if job_info.status == '0': + SchedulerUtil.add_scheduler_job(job_info=job_info) + await query_db.commit() + result = {'is_success': True, 'message': '新增成功'} + except Exception as e: + await query_db.rollback() + raise e return CrudResponseModel(**result) @classmethod - async def edit_job_services(cls, query_db: AsyncSession, page_object: EditJobModel): + def _deal_edit_job(cls, page_object: EditJobModel, edit_job: dict[str, Any]) -> None: + """ + 处理编辑定时任务字典 + + :param page_object: 编辑定时任务对象 + :param edit_job: 编辑定时任务字典 + """ + if page_object.type == 'status': + del edit_job['type'] + + @classmethod + async def edit_job_services(cls, query_db: AsyncSession, page_object: EditJobModel) -> CrudResponseModel: """ 编辑定时任务信息service @@ -101,32 +112,31 @@ class JobService: :return: 编辑定时任务校验结果 """ edit_job = page_object.model_dump(exclude_unset=True) - if page_object.type == 'status': - del edit_job['type'] + cls._deal_edit_job(page_object, edit_job) job_info = await cls.job_detail_services(query_db, page_object.job_id) if job_info: if page_object.type != 'status': if not CronUtil.validate_cron_expression(page_object.cron_expression): raise ServiceException(message=f'修改定时任务{page_object.job_name}失败,Cron表达式不正确') - elif StringUtil.contains_ignore_case(page_object.invoke_target, CommonConstant.LOOKUP_RMI): + if StringUtil.contains_ignore_case(page_object.invoke_target, CommonConstant.LOOKUP_RMI): raise ServiceException(message=f'修改定时任务{page_object.job_name}失败,目标字符串不允许rmi调用') - elif StringUtil.contains_any_ignore_case( + if StringUtil.contains_any_ignore_case( page_object.invoke_target, [CommonConstant.LOOKUP_LDAP, CommonConstant.LOOKUP_LDAPS] ): raise ServiceException( message=f'修改定时任务{page_object.job_name}失败,目标字符串不允许ldap(s)调用' ) - elif StringUtil.contains_any_ignore_case( + if StringUtil.contains_any_ignore_case( page_object.invoke_target, [CommonConstant.HTTP, CommonConstant.HTTPS] ): raise ServiceException( message=f'修改定时任务{page_object.job_name}失败,目标字符串不允许http(s)调用' ) - elif StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_ERROR_LIST): + if StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_ERROR_LIST): raise ServiceException(message=f'修改定时任务{page_object.job_name}失败,目标字符串存在违规') - elif not StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_WHITE_LIST): + if not StringUtil.startswith_any_case(page_object.invoke_target, JobConstant.JOB_WHITE_LIST): raise ServiceException(message=f'修改定时任务{page_object.job_name}失败,目标字符串不在白名单内') - elif not await cls.check_job_unique_services(query_db, page_object): + if not await cls.check_job_unique_services(query_db, page_object): raise ServiceException(message=f'修改定时任务{page_object.job_name}失败,定时任务已存在') try: await JobDao.edit_job_dao(query_db, edit_job, job_info) @@ -143,7 +153,7 @@ class JobService: raise ServiceException(message='定时任务不存在') @classmethod - async def execute_job_once_services(cls, query_db: AsyncSession, page_object: JobModel): + async def execute_job_once_services(cls, query_db: AsyncSession, page_object: JobModel) -> CrudResponseModel: """ 执行一次定时任务service @@ -156,11 +166,10 @@ class JobService: if job_info: SchedulerUtil.execute_scheduler_job_once(job_info=job_info) return CrudResponseModel(is_success=True, message='执行成功') - else: - raise ServiceException(message='定时任务不存在') + raise ServiceException(message='定时任务不存在') @classmethod - async def delete_job_services(cls, query_db: AsyncSession, page_object: DeleteJobModel): + async def delete_job_services(cls, query_db: AsyncSession, page_object: DeleteJobModel) -> CrudResponseModel: """ 删除定时任务信息service @@ -183,7 +192,7 @@ class JobService: raise ServiceException(message='传入定时任务id为空') @classmethod - async def job_detail_services(cls, query_db: AsyncSession, job_id: int): + async def job_detail_services(cls, query_db: AsyncSession, job_id: int) -> JobModel: """ 获取定时任务详细信息service @@ -192,15 +201,12 @@ class JobService: :return: 定时任务id对应的信息 """ job = await JobDao.get_job_detail_by_id(query_db, job_id=job_id) - if job: - result = JobModel(**CamelCaseUtil.transform_result(job)) - else: - result = JobModel(**dict()) + result = JobModel(**CamelCaseUtil.transform_result(job)) if job else JobModel() return result @staticmethod - async def export_job_list_services(request: Request, job_list: List): + async def export_job_list_services(request: Request, job_list: list) -> bytes: """ 导出定时任务信息service @@ -231,13 +237,13 @@ class JobService: job_group_list = await DictDataService.query_dict_data_list_from_cache_services( request.app.state.redis, dict_type='sys_job_group' ) - job_group_option = [dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in job_group_list] + job_group_option = [{'label': item.get('dictLabel'), 'value': item.get('dictValue')} for item in job_group_list] job_group_option_dict = {item.get('value'): item for item in job_group_option} job_executor_list = await DictDataService.query_dict_data_list_from_cache_services( request.app.state.redis, dict_type='sys_job_executor' ) job_executor_option = [ - dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in job_executor_list + {'label': item.get('dictLabel'), 'value': item.get('dictValue')} for item in job_executor_list ] job_executor_option_dict = {item.get('value'): item for item in job_executor_option} @@ -246,9 +252,9 @@ class JobService: item['status'] = '正常' else: item['status'] = '暂停' - if str(item.get('jobGroup')) in job_group_option_dict.keys(): + if str(item.get('jobGroup')) in job_group_option_dict: item['jobGroup'] = job_group_option_dict.get(str(item.get('jobGroup'))).get('label') - if str(item.get('jobExecutor')) in job_executor_option_dict.keys(): + if str(item.get('jobExecutor')) in job_executor_option_dict: item['jobExecutor'] = job_executor_option_dict.get(str(item.get('jobExecutor'))).get('label') if item.get('misfirePolicy') == '1': item['misfirePolicy'] = '立即执行' diff --git a/ruoyi-fastapi-backend/module_admin/service/log_service.py b/ruoyi-fastapi-backend/module_admin/service/log_service.py index 0983b1a..b577834 100644 --- a/ruoyi-fastapi-backend/module_admin/service/log_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/log_service.py @@ -1,6 +1,8 @@ +from typing import Any, Union + from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from exceptions.exception import ServiceException from module_admin.dao.log_dao import LoginLogDao, OperationLogDao from module_admin.entity.vo.common_vo import CrudResponseModel @@ -15,6 +17,7 @@ from module_admin.entity.vo.log_vo import ( ) from module_admin.service.dict_service import DictDataService from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel class OperationLogService: @@ -25,7 +28,7 @@ class OperationLogService: @classmethod async def get_operation_log_list_services( cls, query_db: AsyncSession, query_object: OperLogPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取操作日志列表信息service @@ -39,7 +42,7 @@ class OperationLogService: return operation_log_list_result @classmethod - async def add_operation_log_services(cls, query_db: AsyncSession, page_object: OperLogModel): + async def add_operation_log_services(cls, query_db: AsyncSession, page_object: OperLogModel) -> CrudResponseModel: """ 新增操作日志service @@ -56,7 +59,9 @@ class OperationLogService: raise e @classmethod - async def delete_operation_log_services(cls, query_db: AsyncSession, page_object: DeleteOperLogModel): + async def delete_operation_log_services( + cls, query_db: AsyncSession, page_object: DeleteOperLogModel + ) -> CrudResponseModel: """ 删除操作日志信息service @@ -78,7 +83,7 @@ class OperationLogService: raise ServiceException(message='传入操作日志id为空') @classmethod - async def clear_operation_log_services(cls, query_db: AsyncSession): + async def clear_operation_log_services(cls, query_db: AsyncSession) -> CrudResponseModel: """ 清除操作日志信息service @@ -94,7 +99,7 @@ class OperationLogService: raise e @classmethod - async def export_operation_log_list_services(cls, request: Request, operation_log_list: List): + async def export_operation_log_list_services(cls, request: Request, operation_log_list: list) -> bytes: """ 导出操作日志信息service @@ -126,7 +131,7 @@ class OperationLogService: request.app.state.redis, dict_type='sys_oper_type' ) operation_type_option = [ - dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in operation_type_list + {'label': item.get('dictLabel'), 'value': item.get('dictValue')} for item in operation_type_list ] operation_type_option_dict = {item.get('value'): item for item in operation_type_option} @@ -135,7 +140,7 @@ class OperationLogService: item['status'] = '成功' else: item['status'] = '失败' - if str(item.get('businessType')) in operation_type_option_dict.keys(): + if str(item.get('businessType')) in operation_type_option_dict: item['businessType'] = operation_type_option_dict.get(str(item.get('businessType'))).get('label') binary_data = ExcelUtil.export_list2excel(operation_log_list, mapping_dict) @@ -150,7 +155,7 @@ class LoginLogService: @classmethod async def get_login_log_list_services( cls, query_db: AsyncSession, query_object: LoginLogPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取登录日志列表信息service @@ -164,7 +169,7 @@ class LoginLogService: return operation_log_list_result @classmethod - async def add_login_log_services(cls, query_db: AsyncSession, page_object: LogininforModel): + async def add_login_log_services(cls, query_db: AsyncSession, page_object: LogininforModel) -> CrudResponseModel: """ 新增登录日志service @@ -181,7 +186,9 @@ class LoginLogService: raise e @classmethod - async def delete_login_log_services(cls, query_db: AsyncSession, page_object: DeleteLoginLogModel): + async def delete_login_log_services( + cls, query_db: AsyncSession, page_object: DeleteLoginLogModel + ) -> CrudResponseModel: """ 删除操作日志信息service @@ -203,7 +210,7 @@ class LoginLogService: raise ServiceException(message='传入登录日志id为空') @classmethod - async def clear_login_log_services(cls, query_db: AsyncSession): + async def clear_login_log_services(cls, query_db: AsyncSession) -> CrudResponseModel: """ 清除操作日志信息service @@ -219,16 +226,15 @@ class LoginLogService: raise e @classmethod - async def unlock_user_services(cls, request: Request, unlock_user: UnlockUser): + async def unlock_user_services(cls, request: Request, unlock_user: UnlockUser) -> CrudResponseModel: locked_user = await request.app.state.redis.get(f'account_lock:{unlock_user.user_name}') if locked_user: await request.app.state.redis.delete(f'account_lock:{unlock_user.user_name}') return CrudResponseModel(is_success=True, message='解锁成功') - else: - raise ServiceException(message='该用户未锁定') + raise ServiceException(message='该用户未锁定') @staticmethod - async def export_login_log_list_services(login_log_list: List): + async def export_login_log_list_services(login_log_list: list) -> bytes: """ 导出登录日志信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/login_service.py b/ruoyi-fastapi-backend/module_admin/service/login_service.py index 81c894a..f55eaa8 100644 --- a/ruoyi-fastapi-backend/module_admin/service/login_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/login_service.py @@ -1,20 +1,25 @@ -import jwt import random import uuid from datetime import datetime, timedelta, timezone +from typing import Any, Optional, Union + +import jwt from fastapi import Depends, Form, Request from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jwt.exceptions import InvalidTokenError +from sqlalchemy import Row from sqlalchemy.ext.asyncio import AsyncSession -from typing import Dict, List, Optional, Union + from config.constant import CommonConstant, MenuConstant from config.enums import RedisInitKeyConfig from config.env import AppConfig, JwtConfig from config.get_db import get_db -from exceptions.exception import LoginException, AuthException, ServiceException +from exceptions.exception import AuthException, LoginException, ServiceException from module_admin.dao.login_dao import login_by_account from module_admin.dao.user_dao import UserDao +from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.menu_do import SysMenu +from module_admin.entity.do.user_do import SysUser from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.login_vo import MenuTreeModel, MetaModel, RouterModel, SmsCode, UserLogin, UserRegister from module_admin.entity.vo.user_vo import AddUserModel, CurrentUserModel, ResetUserModel, TokenData, UserInfoModel @@ -42,8 +47,8 @@ class CustomOAuth2PasswordRequestForm(OAuth2PasswordRequestForm): client_secret: Optional[str] = Form(default=None), code: Optional[str] = Form(default=''), uuid: Optional[str] = Form(default=''), - login_info: Optional[Dict[str, str]] = Form(default=None), - ): + login_info: Optional[dict[str, str]] = Form(default=None), + ) -> None: super().__init__( grant_type=grant_type, username=username, @@ -63,7 +68,9 @@ class LoginService: """ @classmethod - async def authenticate_user(cls, request: Request, query_db: AsyncSession, login_user: UserLogin): + async def authenticate_user( + cls, request: Request, query_db: AsyncSession, login_user: UserLogin + ) -> Row[tuple[SysUser, SysDept]]: """ 根据用户名密码校验用户登录 @@ -110,7 +117,7 @@ class LoginService: password_error_count, ex=timedelta(minutes=10), ) - if password_error_count > 5: + if password_error_count > CommonConstant.PASSWORD_ERROR_COUNT: await request.app.state.redis.delete( f'{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.key}:{login_user.user_name}' ) @@ -130,7 +137,7 @@ class LoginService: return user @classmethod - async def __check_login_ip(cls, request: Request): + async def __check_login_ip(cls, request: Request) -> bool: """ 校验用户登录ip是否在黑名单内 @@ -145,7 +152,7 @@ class LoginService: return True @classmethod - async def __check_login_captcha(cls, request: Request, login_user: UserLogin): + async def __check_login_captcha(cls, request: Request, login_user: UserLogin) -> bool: """ 校验用户登录验证码 @@ -163,7 +170,7 @@ class LoginService: return True @classmethod - async def create_access_token(cls, data: dict, expires_delta: Union[timedelta, None] = None): + async def create_access_token(cls, data: dict, expires_delta: Union[timedelta, None] = None) -> str: """ 根据登录信息创建当前用户token @@ -183,7 +190,7 @@ class LoginService: @classmethod async def get_current_user( cls, request: Request = Request, token: str = Depends(oauth2_scheme), query_db: AsyncSession = Depends(get_db) - ): + ) -> CurrentUserModel: """ 根据token获取当前用户信息 @@ -206,9 +213,9 @@ class LoginService: logger.warning('用户token不合法') raise AuthException(data='', message='用户token不合法') token_data = TokenData(user_id=int(user_id)) - except InvalidTokenError: + except InvalidTokenError as e: logger.warning('用户token已失效,请重新登录') - raise AuthException(data='', message='用户token已失效,请重新登录') + raise AuthException(data='', message='用户token已失效,请重新登录') from e query_user = await UserDao.get_user_by_id(query_db, user_id=token_data.user_id) if query_user.get('user_basic_info') is None: logger.warning('用户token不合法') @@ -235,7 +242,7 @@ class LoginService: ) role_id_list = [item.role_id for item in query_user.get('user_role_info')] - if 1 in role_id_list: + if 1 in role_id_list: # noqa: SIM108 permissions = ['*:*:*'] else: permissions = [row.perms for row in query_user.get('user_menu_info')] @@ -263,12 +270,11 @@ class LoginService: isPasswordExpired=is_password_expired, ) return current_user - else: - logger.warning('用户token已失效,请重新登录') - raise AuthException(data='', message='用户token已失效,请重新登录') + logger.warning('用户token已失效,请重新登录') + raise AuthException(data='', message='用户token已失效,请重新登录') @classmethod - async def __init_password_is_modify(cls, request: Request, pwd_update_date: datetime): + async def __init_password_is_modify(cls, request: Request, pwd_update_date: datetime) -> bool: """ 判断当前用户是否初始密码登录 @@ -282,7 +288,7 @@ class LoginService: return init_password_is_modify == '1' and pwd_update_date is None @classmethod - async def __password_is_expired(cls, request: Request, pwd_update_date: datetime): + async def __password_is_expired(cls, request: Request, pwd_update_date: datetime) -> bool: """ 判断当前用户密码是否过期 @@ -302,7 +308,7 @@ class LoginService: return False @classmethod - async def get_current_user_routers(cls, user_id: int, query_db: AsyncSession): + async def get_current_user_routers(cls, user_id: int, query_db: AsyncSession) -> list[dict[str, Any]]: """ 根据用户id获取当前用户路由信息 @@ -324,7 +330,7 @@ class LoginService: return [router.model_dump(exclude_unset=True, by_alias=True) for router in user_router] @classmethod - def __generate_menus(cls, pid: int, permission_list: List[SysMenu]): + def __generate_menus(cls, pid: int, permission_list: list[SysMenu]) -> list[MenuTreeModel]: """ 工具方法:根据菜单信息生成菜单信息树形嵌套数据 @@ -332,7 +338,7 @@ class LoginService: :param permission_list: 菜单列表信息 :return: 菜单信息树形嵌套数据 """ - menu_list: List[MenuTreeModel] = [] + menu_list: list[MenuTreeModel] = [] for permission in permission_list: if permission.parent_id == pid: children = cls.__generate_menus(permission.menu_id, permission_list) @@ -344,17 +350,17 @@ class LoginService: return menu_list @classmethod - def __generate_user_router_menu(cls, permission_list: List[MenuTreeModel]): + def __generate_user_router_menu(cls, permission_list: list[MenuTreeModel]) -> list[RouterModel]: """ 工具方法:根据菜单树信息生成路由信息树形嵌套数据 :param permission_list: 菜单树列表信息 :return: 路由信息树形嵌套数据 """ - router_list: List[RouterModel] = [] + router_list: list[RouterModel] = [] for permission in permission_list: router = RouterModel( - hidden=True if permission.visible == '1' else False, + hidden=permission.visible == '1', name=RouterUtil.get_router_name(permission), path=RouterUtil.get_router_path(permission), component=RouterUtil.get_component(permission), @@ -362,7 +368,7 @@ class LoginService: meta=MetaModel( title=permission.menu_name, icon=permission.icon, - noCache=True if permission.is_cache == 1 else False, + noCache=permission.is_cache == 1, link=permission.path if RouterUtil.is_http(permission.path) else None, ), ) @@ -373,7 +379,7 @@ class LoginService: router.children = cls.__generate_user_router_menu(c_menus) elif RouterUtil.is_menu_frame(permission): router.meta = None - children_list: List[RouterModel] = [] + children_list: list[RouterModel] = [] children = RouterModel( path=permission.path, component=permission.component, @@ -381,7 +387,7 @@ class LoginService: meta=MetaModel( title=permission.menu_name, icon=permission.icon, - noCache=True if permission.is_cache == 1 else False, + noCache=permission.is_cache == 1, link=permission.path if RouterUtil.is_http(permission.path) else None, ), query=permission.query, @@ -391,7 +397,7 @@ class LoginService: elif permission.parent_id == 0 and RouterUtil.is_inner_link(permission): router.meta = MetaModel(title=permission.menu_name, icon=permission.icon) router.path = '/' - children_list: List[RouterModel] = [] + children_list: list[RouterModel] = [] router_path = RouterUtil.inner_link_replace_each(permission.path) children = RouterModel( path=router_path, @@ -411,7 +417,9 @@ class LoginService: return router_list @classmethod - async def register_user_services(cls, request: Request, query_db: AsyncSession, user_register: UserRegister): + async def register_user_services( + cls, request: Request, query_db: AsyncSession, user_register: UserRegister + ) -> CrudResponseModel: """ 用户注册services @@ -421,16 +429,11 @@ class LoginService: :return: 注册结果 """ register_enabled = ( - True - if await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.registerUser') - == 'true' - else False + await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.registerUser') == 'true' ) captcha_enabled = ( - True - if await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') + await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true' - else False ) if user_register.password == user_register.confirm_password: if register_enabled: @@ -440,7 +443,7 @@ class LoginService: ) if not captcha_value: raise ServiceException(message='验证码已失效') - elif user_register.code != str(captcha_value): + if user_register.code != str(captcha_value): raise ServiceException(message='验证码错误') add_user = AddUserModel( userName=user_register.username, @@ -450,13 +453,11 @@ class LoginService: ) result = await UserService.add_user_services(query_db, add_user) return result - else: - raise ServiceException(message='注册程序已关闭,禁止注册') - else: - raise ServiceException(message='两次输入的密码不一致') + raise ServiceException(message='注册程序已关闭,禁止注册') + raise ServiceException(message='两次输入的密码不一致') @classmethod - async def get_sms_code_services(cls, request: Request, query_db: AsyncSession, user: ResetUserModel): + async def get_sms_code_services(cls, request: Request, query_db: AsyncSession, user: ResetUserModel) -> SmsCode: """ 获取短信验证码service @@ -467,7 +468,7 @@ class LoginService: """ redis_sms_result = await request.app.state.redis.get(f'{RedisInitKeyConfig.SMS_CODE.key}:{user.session_id}') if redis_sms_result: - return SmsCode(**dict(is_success=False, sms_code='', session_id='', message='短信验证码仍在有效期内')) + return SmsCode(is_success=False, sms_code='', session_id='', message='短信验证码仍在有效期内') is_user = await UserDao.get_user_by_name(query_db, user.user_name) if is_user: sms_code = str(random.randint(100000, 999999)) @@ -478,12 +479,14 @@ class LoginService: # 此处模拟调用短信服务 message_service(sms_code) - return SmsCode(**dict(is_success=True, sms_code=sms_code, session_id=session_id, message='获取成功')) + return SmsCode(is_success=True, sms_code=sms_code, session_id=session_id, message='获取成功') - return SmsCode(**dict(is_success=False, sms_code='', session_id='', message='用户不存在')) + return SmsCode(is_success=False, sms_code='', session_id='', message='用户不存在') @classmethod - async def forget_user_services(cls, request: Request, query_db: AsyncSession, forget_user: ResetUserModel): + async def forget_user_services( + cls, request: Request, query_db: AsyncSession, forget_user: ResetUserModel + ) -> CrudResponseModel: """ 用户忘记密码services @@ -501,15 +504,15 @@ class LoginService: edit_result = await UserService.reset_user_services(query_db, forget_user) result = edit_result.dict() elif not redis_sms_result: - result = dict(is_success=False, message='短信验证码已过期') + result = {'is_success': False, 'message': '短信验证码已过期'} else: await request.app.state.redis.delete(f'{RedisInitKeyConfig.SMS_CODE.key}:{forget_user.session_id}') - result = dict(is_success=False, message='短信验证码不正确') + result = {'is_success': False, 'message': '短信验证码不正确'} return CrudResponseModel(**result) @classmethod - async def logout_services(cls, request: Request, token_id: str): + async def logout_services(cls, request: Request, token_id: str) -> bool: """ 退出登录services @@ -530,7 +533,7 @@ class RouterUtil: """ @classmethod - def get_router_name(cls, menu: MenuTreeModel): + def get_router_name(cls, menu: MenuTreeModel) -> str: """ 获取路由名称 @@ -544,7 +547,7 @@ class RouterUtil: return cls.get_route_name(menu.route_name, menu.path) @classmethod - def get_route_name(cls, name: str, path: str): + def get_route_name(cls, name: str, path: str) -> str: """ 获取路由名称,如没有配置路由名称则取路由地址 @@ -556,7 +559,7 @@ class RouterUtil: return router_name.capitalize() @classmethod - def get_router_path(cls, menu: MenuTreeModel): + def get_router_path(cls, menu: MenuTreeModel) -> Union[str, None]: """ 获取路由地址 @@ -576,7 +579,7 @@ class RouterUtil: return router_path @classmethod - def get_component(cls, menu: MenuTreeModel): + def get_component(cls, menu: MenuTreeModel) -> str: """ 获取组件信息 @@ -593,7 +596,7 @@ class RouterUtil: return component @classmethod - def is_menu_frame(cls, menu: MenuTreeModel): + def is_menu_frame(cls, menu: MenuTreeModel) -> bool: """ 判断是否为菜单内部跳转 @@ -605,7 +608,7 @@ class RouterUtil: ) @classmethod - def is_inner_link(cls, menu: MenuTreeModel): + def is_inner_link(cls, menu: MenuTreeModel) -> bool: """ 判断是否为内链组件 @@ -615,7 +618,7 @@ class RouterUtil: return menu.is_frame == MenuConstant.NO_FRAME and cls.is_http(menu.path) @classmethod - def is_parent_view(cls, menu: MenuTreeModel): + def is_parent_view(cls, menu: MenuTreeModel) -> bool: """ 判断是否为parent_view组件 @@ -625,17 +628,17 @@ class RouterUtil: return menu.parent_id != 0 and menu.menu_type == MenuConstant.TYPE_DIR @classmethod - def is_http(cls, link: str): + def is_http(cls, link: str) -> bool: """ 判断是否为http(s)://开头 :param link: 链接 :return: 是否为http(s)://开头 """ - return link.startswith(CommonConstant.HTTP) or link.startswith(CommonConstant.HTTPS) + return link.startswith((CommonConstant.HTTP, CommonConstant.HTTPS)) @classmethod - def inner_link_replace_each(cls, path: str): + def inner_link_replace_each(cls, path: str) -> str: """ 内链域名特殊字符替换 diff --git a/ruoyi-fastapi-backend/module_admin/service/menu_service.py b/ruoyi-fastapi-backend/module_admin/service/menu_service.py index cb6368a..6c403d5 100644 --- a/ruoyi-fastapi-backend/module_admin/service/menu_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/menu_service.py @@ -1,11 +1,15 @@ +from collections.abc import Sequence +from typing import Any, Optional + from sqlalchemy.ext.asyncio import AsyncSession -from typing import Optional + from config.constant import CommonConstant, MenuConstant from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.menu_dao import MenuDao from module_admin.dao.role_dao import RoleDao +from module_admin.entity.do.menu_do import SysMenu from module_admin.entity.vo.common_vo import CrudResponseModel -from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuQueryModel, MenuModel +from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel from module_admin.entity.vo.role_vo import RoleMenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from utils.common_util import CamelCaseUtil @@ -18,7 +22,9 @@ class MenuService: """ @classmethod - async def get_menu_tree_services(cls, query_db: AsyncSession, current_user: Optional[CurrentUserModel] = None): + async def get_menu_tree_services( + cls, query_db: AsyncSession, current_user: Optional[CurrentUserModel] = None + ) -> list[dict[str, Any]]: """ 获取菜单树信息service @@ -36,7 +42,7 @@ class MenuService: @classmethod async def get_role_menu_tree_services( cls, query_db: AsyncSession, role_id: int, current_user: Optional[CurrentUserModel] = None - ): + ) -> RoleMenuQueryModel: """ 根据角色id获取菜单树信息service @@ -59,7 +65,7 @@ class MenuService: @classmethod async def get_menu_list_services( cls, query_db: AsyncSession, page_object: MenuQueryModel, current_user: Optional[CurrentUserModel] = None - ): + ) -> list[dict[str, Any]]: """ 获取菜单列表信息service @@ -75,7 +81,7 @@ class MenuService: return CamelCaseUtil.transform_result(menu_list_result) @classmethod - async def check_menu_name_unique_services(cls, query_db: AsyncSession, page_object: MenuModel): + async def check_menu_name_unique_services(cls, query_db: AsyncSession, page_object: MenuModel) -> bool: """ 校验菜单名称是否唯一service @@ -90,7 +96,7 @@ class MenuService: return CommonConstant.UNIQUE @classmethod - async def add_menu_services(cls, query_db: AsyncSession, page_object: MenuModel): + async def add_menu_services(cls, query_db: AsyncSession, page_object: MenuModel) -> CrudResponseModel: """ 新增菜单信息service @@ -100,19 +106,18 @@ class MenuService: """ if not await cls.check_menu_name_unique_services(query_db, page_object): raise ServiceException(message=f'新增菜单{page_object.menu_name}失败,菜单名称已存在') - elif page_object.is_frame == MenuConstant.YES_FRAME and not StringUtil.is_http(page_object.path): + if page_object.is_frame == MenuConstant.YES_FRAME and not StringUtil.is_http(page_object.path): raise ServiceException(message=f'新增菜单{page_object.menu_name}失败,地址必须以http(s)://开头') - else: - try: - await MenuDao.add_menu_dao(query_db, page_object) - await query_db.commit() - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await MenuDao.add_menu_dao(query_db, page_object) + await query_db.commit() + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_menu_services(cls, query_db: AsyncSession, page_object: MenuModel): + async def edit_menu_services(cls, query_db: AsyncSession, page_object: MenuModel) -> CrudResponseModel: """ 编辑菜单信息service @@ -125,23 +130,22 @@ class MenuService: if menu_info.menu_id: if not await cls.check_menu_name_unique_services(query_db, page_object): raise ServiceException(message=f'修改菜单{page_object.menu_name}失败,菜单名称已存在') - elif page_object.is_frame == MenuConstant.YES_FRAME and not StringUtil.is_http(page_object.path): + if page_object.is_frame == MenuConstant.YES_FRAME and not StringUtil.is_http(page_object.path): raise ServiceException(message=f'修改菜单{page_object.menu_name}失败,地址必须以http(s)://开头') - elif page_object.menu_id == page_object.parent_id: + if page_object.menu_id == page_object.parent_id: raise ServiceException(message=f'修改菜单{page_object.menu_name}失败,上级菜单不能选择自己') - else: - try: - await MenuDao.edit_menu_dao(query_db, edit_menu) - await query_db.commit() - return CrudResponseModel(is_success=True, message='更新成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await MenuDao.edit_menu_dao(query_db, edit_menu) + await query_db.commit() + return CrudResponseModel(is_success=True, message='更新成功') + except Exception as e: + await query_db.rollback() + raise e else: raise ServiceException(message='菜单不存在') @classmethod - async def delete_menu_services(cls, query_db: AsyncSession, page_object: DeleteMenuModel): + async def delete_menu_services(cls, query_db: AsyncSession, page_object: DeleteMenuModel) -> CrudResponseModel: """ 删除菜单信息service @@ -155,7 +159,7 @@ class MenuService: for menu_id in menu_id_list: if (await MenuDao.has_child_by_menu_id_dao(query_db, int(menu_id))) > 0: raise ServiceWarning(message='存在子菜单,不允许删除') - elif (await MenuDao.check_menu_exist_role_dao(query_db, int(menu_id))) > 0: + if (await MenuDao.check_menu_exist_role_dao(query_db, int(menu_id))) > 0: raise ServiceWarning(message='菜单已分配,不允许删除') await MenuDao.delete_menu_dao(query_db, MenuModel(menuId=menu_id)) await query_db.commit() @@ -167,7 +171,7 @@ class MenuService: raise ServiceException(message='传入菜单id为空') @classmethod - async def menu_detail_services(cls, query_db: AsyncSession, menu_id: int): + async def menu_detail_services(cls, query_db: AsyncSession, menu_id: int) -> MenuModel: """ 获取菜单详细信息service @@ -176,37 +180,34 @@ class MenuService: :return: 菜单id对应的信息 """ menu = await MenuDao.get_menu_detail_by_id(query_db, menu_id=menu_id) - if menu: - result = MenuModel(**CamelCaseUtil.transform_result(menu)) - else: - result = MenuModel(**dict()) + result = MenuModel(**CamelCaseUtil.transform_result(menu)) if menu else MenuModel() return result @classmethod - def list_to_tree(cls, permission_list: list) -> list: + def list_to_tree(cls, permission_list: Sequence[SysMenu]) -> list[dict[str, Any]]: """ 工具方法:根据菜单列表信息生成树形嵌套数据 :param permission_list: 菜单列表信息 :return: 菜单树形嵌套数据 """ - permission_list = [ - dict(id=item.menu_id, label=item.menu_name, parentId=item.parent_id) for item in permission_list + _permission_list = [ + {'id': item.menu_id, 'label': item.menu_name, 'parentId': item.parent_id} for item in permission_list ] # 转成id为key的字典 - mapping: dict = dict(zip([i['id'] for i in permission_list], permission_list)) + mapping: dict[int, dict[str, Any]] = dict(zip([i['id'] for i in _permission_list], _permission_list)) # 树容器 - container: list = [] + container: list[dict[str, Any]] = [] - for d in permission_list: + for d in _permission_list: # 如果找不到父级项,则是根节点 - parent: dict = mapping.get(d['parentId']) + parent = mapping.get(d['parentId']) if parent is None: container.append(d) else: - children: list = parent.get('children') + children: list[dict[str, Any]] = parent.get('children') if not children: children = [] children.append(d) diff --git a/ruoyi-fastapi-backend/module_admin/service/notice_service.py b/ruoyi-fastapi-backend/module_admin/service/notice_service.py index 4671703..51452e6 100644 --- a/ruoyi-fastapi-backend/module_admin/service/notice_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/notice_service.py @@ -1,10 +1,14 @@ +from typing import Any, Union + from sqlalchemy.ext.asyncio import AsyncSession + from config.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.notice_dao import NoticeDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from utils.common_util import CamelCaseUtil +from utils.page_util import PageResponseModel class NoticeService: @@ -15,7 +19,7 @@ class NoticeService: @classmethod async def get_notice_list_services( cls, query_db: AsyncSession, query_object: NoticePageQueryModel, is_page: bool = True - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取通知公告列表信息service @@ -29,7 +33,7 @@ class NoticeService: return notice_list_result @classmethod - async def check_notice_unique_services(cls, query_db: AsyncSession, page_object: NoticeModel): + async def check_notice_unique_services(cls, query_db: AsyncSession, page_object: NoticeModel) -> bool: """ 校验通知公告是否存在service @@ -44,7 +48,7 @@ class NoticeService: return CommonConstant.UNIQUE @classmethod - async def add_notice_services(cls, query_db: AsyncSession, page_object: NoticeModel): + async def add_notice_services(cls, query_db: AsyncSession, page_object: NoticeModel) -> CrudResponseModel: """ 新增通知公告信息service @@ -54,17 +58,16 @@ class NoticeService: """ if not await cls.check_notice_unique_services(query_db, page_object): raise ServiceException(message=f'新增通知公告{page_object.notice_title}失败,通知公告已存在') - else: - try: - await NoticeDao.add_notice_dao(query_db, page_object) - await query_db.commit() - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await NoticeDao.add_notice_dao(query_db, page_object) + await query_db.commit() + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_notice_services(cls, query_db: AsyncSession, page_object: NoticeModel): + async def edit_notice_services(cls, query_db: AsyncSession, page_object: NoticeModel) -> CrudResponseModel: """ 编辑通知公告信息service @@ -77,19 +80,18 @@ class NoticeService: if notice_info.notice_id: if not await cls.check_notice_unique_services(query_db, page_object): raise ServiceException(message=f'修改通知公告{page_object.notice_title}失败,通知公告已存在') - else: - try: - await NoticeDao.edit_notice_dao(query_db, edit_notice) - await query_db.commit() - return CrudResponseModel(is_success=True, message='更新成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await NoticeDao.edit_notice_dao(query_db, edit_notice) + await query_db.commit() + return CrudResponseModel(is_success=True, message='更新成功') + except Exception as e: + await query_db.rollback() + raise e else: raise ServiceException(message='通知公告不存在') @classmethod - async def delete_notice_services(cls, query_db: AsyncSession, page_object: DeleteNoticeModel): + async def delete_notice_services(cls, query_db: AsyncSession, page_object: DeleteNoticeModel) -> CrudResponseModel: """ 删除通知公告信息service @@ -111,7 +113,7 @@ class NoticeService: raise ServiceException(message='传入通知公告id为空') @classmethod - async def notice_detail_services(cls, query_db: AsyncSession, notice_id: int): + async def notice_detail_services(cls, query_db: AsyncSession, notice_id: int) -> NoticeModel: """ 获取通知公告详细信息service @@ -120,9 +122,6 @@ class NoticeService: :return: 通知公告id对应的信息 """ notice = await NoticeDao.get_notice_detail_by_id(query_db, notice_id=notice_id) - if notice: - result = NoticeModel(**CamelCaseUtil.transform_result(notice)) - else: - result = NoticeModel(**dict()) + result = NoticeModel(**CamelCaseUtil.transform_result(notice)) if notice else NoticeModel() return result diff --git a/ruoyi-fastapi-backend/module_admin/service/online_service.py b/ruoyi-fastapi-backend/module_admin/service/online_service.py index 56742b0..2ba06c4 100644 --- a/ruoyi-fastapi-backend/module_admin/service/online_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/online_service.py @@ -1,5 +1,8 @@ +from typing import Any + import jwt from fastapi import Request + from config.enums import RedisInitKeyConfig from config.env import JwtConfig from exceptions.exception import ServiceException @@ -14,7 +17,7 @@ class OnlineService: """ @classmethod - async def get_online_list_services(cls, request: Request, query_object: OnlineQueryModel): + async def get_online_list_services(cls, request: Request, query_object: OnlineQueryModel) -> list[dict[str, Any]]: """ 获取在线用户表信息service @@ -29,16 +32,16 @@ class OnlineService: online_info_list = [] for item in access_token_values_list: payload = jwt.decode(item, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm]) - online_dict = dict( - token_id=payload.get('session_id'), - user_name=payload.get('user_name'), - dept_name=payload.get('dept_name'), - ipaddr=payload.get('login_info').get('ipaddr'), - login_location=payload.get('login_info').get('loginLocation'), - browser=payload.get('login_info').get('browser'), - os=payload.get('login_info').get('os'), - login_time=payload.get('login_info').get('loginTime'), - ) + online_dict = { + 'token_id': payload.get('session_id'), + 'user_name': payload.get('user_name'), + 'dept_name': payload.get('dept_name'), + 'ipaddr': payload.get('login_info').get('ipaddr'), + 'login_location': payload.get('login_info').get('loginLocation'), + 'browser': payload.get('login_info').get('browser'), + 'os': payload.get('login_info').get('os'), + 'login_time': payload.get('login_info').get('loginTime'), + } if query_object.user_name and not query_object.ipaddr: if query_object.user_name == payload.get('user_name'): online_info_list = [online_dict] @@ -59,7 +62,7 @@ class OnlineService: return CamelCaseUtil.transform_result(online_info_list) @classmethod - async def delete_online_services(cls, request: Request, page_object: DeleteOnlineModel): + async def delete_online_services(cls, request: Request, page_object: DeleteOnlineModel) -> CrudResponseModel: """ 强退在线用户信息service @@ -72,5 +75,4 @@ class OnlineService: for token_id in token_id_list: await request.app.state.redis.delete(f'{RedisInitKeyConfig.ACCESS_TOKEN.key}:{token_id}') return CrudResponseModel(is_success=True, message='强退成功') - else: - raise ServiceException(message='传入session_id为空') + raise ServiceException(message='传入session_id为空') diff --git a/ruoyi-fastapi-backend/module_admin/service/post_service.py b/ruoyi-fastapi-backend/module_admin/service/post_service.py index 9338a9f..f82016e 100644 --- a/ruoyi-fastapi-backend/module_admin/service/post_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/post_service.py @@ -1,5 +1,7 @@ +from typing import Any, Union + from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.post_dao import PostDao @@ -7,6 +9,7 @@ from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel class PostService: @@ -17,7 +20,7 @@ class PostService: @classmethod async def get_post_list_services( cls, query_db: AsyncSession, query_object: PostPageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取岗位列表信息service @@ -31,7 +34,7 @@ class PostService: return post_list_result @classmethod - async def check_post_name_unique_services(cls, query_db: AsyncSession, page_object: PostModel): + async def check_post_name_unique_services(cls, query_db: AsyncSession, page_object: PostModel) -> bool: """ 检查岗位名称是否唯一service @@ -46,7 +49,7 @@ class PostService: return CommonConstant.UNIQUE @classmethod - async def check_post_code_unique_services(cls, query_db: AsyncSession, page_object: PostModel): + async def check_post_code_unique_services(cls, query_db: AsyncSession, page_object: PostModel) -> bool: """ 检查岗位编码是否唯一service @@ -61,7 +64,7 @@ class PostService: return CommonConstant.UNIQUE @classmethod - async def add_post_services(cls, query_db: AsyncSession, page_object: PostModel): + async def add_post_services(cls, query_db: AsyncSession, page_object: PostModel) -> CrudResponseModel: """ 新增岗位信息service @@ -71,19 +74,18 @@ class PostService: """ if not await cls.check_post_name_unique_services(query_db, page_object): raise ServiceException(message=f'新增岗位{page_object.post_name}失败,岗位名称已存在') - elif not await cls.check_post_code_unique_services(query_db, page_object): + if not await cls.check_post_code_unique_services(query_db, page_object): raise ServiceException(message=f'新增岗位{page_object.post_name}失败,岗位编码已存在') - else: - try: - await PostDao.add_post_dao(query_db, page_object) - await query_db.commit() - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await PostDao.add_post_dao(query_db, page_object) + await query_db.commit() + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_post_services(cls, query_db: AsyncSession, page_object: PostModel): + async def edit_post_services(cls, query_db: AsyncSession, page_object: PostModel) -> CrudResponseModel: """ 编辑岗位信息service @@ -96,21 +98,20 @@ class PostService: if post_info.post_id: if not await cls.check_post_name_unique_services(query_db, page_object): raise ServiceException(message=f'修改岗位{page_object.post_name}失败,岗位名称已存在') - elif not await cls.check_post_code_unique_services(query_db, page_object): + if not await cls.check_post_code_unique_services(query_db, page_object): raise ServiceException(message=f'修改岗位{page_object.post_name}失败,岗位编码已存在') - else: - try: - await PostDao.edit_post_dao(query_db, edit_post) - await query_db.commit() - return CrudResponseModel(is_success=True, message='更新成功') - except Exception as e: - await query_db.rollback() - raise e + try: + await PostDao.edit_post_dao(query_db, edit_post) + await query_db.commit() + return CrudResponseModel(is_success=True, message='更新成功') + except Exception as e: + await query_db.rollback() + raise e else: raise ServiceException(message='岗位不存在') @classmethod - async def delete_post_services(cls, query_db: AsyncSession, page_object: DeletePostModel): + async def delete_post_services(cls, query_db: AsyncSession, page_object: DeletePostModel) -> CrudResponseModel: """ 删除岗位信息service @@ -135,7 +136,7 @@ class PostService: raise ServiceException(message='传入岗位id为空') @classmethod - async def post_detail_services(cls, query_db: AsyncSession, post_id: int): + async def post_detail_services(cls, query_db: AsyncSession, post_id: int) -> PostModel: """ 获取岗位详细信息service @@ -144,15 +145,12 @@ class PostService: :return: 岗位id对应的信息 """ post = await PostDao.get_post_detail_by_id(query_db, post_id=post_id) - if post: - result = PostModel(**CamelCaseUtil.transform_result(post)) - else: - result = PostModel(**dict()) + result = PostModel(**CamelCaseUtil.transform_result(post)) if post else PostModel() return result @staticmethod - async def export_post_list_services(post_list: List): + async def export_post_list_services(post_list: list) -> bytes: """ 导出岗位信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index 4b633de..a0eaf91 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -1,7 +1,11 @@ +from typing import Any, Union + from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.constant import CommonConstant from exceptions.exception import ServiceException +from module_admin.dao.role_dao import RoleDao +from module_admin.dao.user_dao import UserDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.role_vo import ( AddRoleModel, @@ -13,8 +17,6 @@ from module_admin.entity.vo.role_vo import ( RolePageQueryModel, ) from module_admin.entity.vo.user_vo import UserInfoModel, UserRolePageQueryModel -from module_admin.dao.role_dao import RoleDao -from module_admin.dao.user_dao import UserDao from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil from utils.page_util import PageResponseModel @@ -26,7 +28,7 @@ class RoleService: """ @classmethod - async def get_role_select_option_services(cls, query_db: AsyncSession): + async def get_role_select_option_services(cls, query_db: AsyncSession) -> list[dict[str, Any]]: """ 获取角色列表不分页信息service @@ -38,7 +40,7 @@ class RoleService: return CamelCaseUtil.transform_result(role_list_result) @classmethod - async def get_role_dept_tree_services(cls, query_db: AsyncSession, role_id: int): + async def get_role_dept_tree_services(cls, query_db: AsyncSession, role_id: int) -> RoleDeptQueryModel: """ 根据角色id获取部门树信息service @@ -56,7 +58,7 @@ class RoleService: @classmethod async def get_role_list_services( cls, query_db: AsyncSession, query_object: RolePageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取角色列表信息service @@ -71,7 +73,7 @@ class RoleService: return role_list_result @classmethod - async def check_role_allowed_services(cls, check_role: RoleModel): + async def check_role_allowed_services(cls, check_role: RoleModel) -> CrudResponseModel: """ 校验角色是否允许操作service @@ -80,11 +82,10 @@ class RoleService: """ if check_role.admin: raise ServiceException(message='不允许操作超级管理员角色') - else: - return CrudResponseModel(is_success=True, message='校验通过') + return CrudResponseModel(is_success=True, message='校验通过') @classmethod - async def check_role_data_scope_services(cls, query_db: AsyncSession, role_ids: str, data_scope_sql: str): + async def check_role_data_scope_services(cls, query_db: AsyncSession, role_ids: str, data_scope_sql: str) -> None: """ 校验角色是否有数据权限service @@ -101,11 +102,10 @@ class RoleService: ) if roles: continue - else: - raise ServiceException(message='没有权限访问角色数据') + raise ServiceException(message='没有权限访问角色数据') @classmethod - async def check_role_name_unique_services(cls, query_db: AsyncSession, page_object: RoleModel): + async def check_role_name_unique_services(cls, query_db: AsyncSession, page_object: RoleModel) -> bool: """ 校验角色名称是否唯一service @@ -120,7 +120,7 @@ class RoleService: return CommonConstant.UNIQUE @classmethod - async def check_role_key_unique_services(cls, query_db: AsyncSession, page_object: RoleModel): + async def check_role_key_unique_services(cls, query_db: AsyncSession, page_object: RoleModel) -> bool: """ 校验角色权限字符是否唯一service @@ -135,7 +135,7 @@ class RoleService: return CommonConstant.UNIQUE @classmethod - async def add_role_services(cls, query_db: AsyncSession, page_object: AddRoleModel): + async def add_role_services(cls, query_db: AsyncSession, page_object: AddRoleModel) -> CrudResponseModel: """ 新增角色信息service @@ -146,23 +146,22 @@ class RoleService: add_role = RoleModel(**page_object.model_dump(by_alias=True)) if not await cls.check_role_name_unique_services(query_db, page_object): raise ServiceException(message=f'新增角色{page_object.role_name}失败,角色名称已存在') - elif not await cls.check_role_key_unique_services(query_db, page_object): + if not await cls.check_role_key_unique_services(query_db, page_object): raise ServiceException(message=f'新增角色{page_object.role_name}失败,角色权限已存在') - else: - try: - add_result = await RoleDao.add_role_dao(query_db, add_role) - role_id = add_result.role_id - if page_object.menu_ids: - for menu in page_object.menu_ids: - await RoleDao.add_role_menu_dao(query_db, RoleMenuModel(roleId=role_id, menuId=menu)) - await query_db.commit() - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + add_result = await RoleDao.add_role_dao(query_db, add_role) + role_id = add_result.role_id + if page_object.menu_ids: + for menu in page_object.menu_ids: + await RoleDao.add_role_menu_dao(query_db, RoleMenuModel(roleId=role_id, menuId=menu)) + await query_db.commit() + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_role_services(cls, query_db: AsyncSession, page_object: AddRoleModel): + async def edit_role_services(cls, query_db: AsyncSession, page_object: AddRoleModel) -> CrudResponseModel: """ 编辑角色信息service @@ -180,7 +179,7 @@ class RoleService: if page_object.type != 'status': if not await cls.check_role_name_unique_services(query_db, page_object): raise ServiceException(message=f'修改角色{page_object.role_name}失败,角色名称已存在') - elif not await cls.check_role_key_unique_services(query_db, page_object): + if not await cls.check_role_key_unique_services(query_db, page_object): raise ServiceException(message=f'修改角色{page_object.role_name}失败,角色权限已存在') try: await RoleDao.edit_role_dao(query_db, edit_role) @@ -200,7 +199,7 @@ class RoleService: raise ServiceException(message='角色不存在') @classmethod - async def role_datascope_services(cls, query_db: AsyncSession, page_object: AddRoleModel): + async def role_datascope_services(cls, query_db: AsyncSession, page_object: AddRoleModel) -> CrudResponseModel: """ 分配角色数据权限service @@ -228,7 +227,7 @@ class RoleService: raise ServiceException(message='角色不存在') @classmethod - async def delete_role_services(cls, query_db: AsyncSession, page_object: DeleteRoleModel): + async def delete_role_services(cls, query_db: AsyncSession, page_object: DeleteRoleModel) -> CrudResponseModel: """ 删除角色信息service @@ -243,9 +242,11 @@ class RoleService: role = await cls.role_detail_services(query_db, int(role_id)) if (await RoleDao.count_user_role_dao(query_db, int(role_id))) > 0: raise ServiceException(message=f'角色{role.role_name}已分配,不能删除') - role_id_dict = dict( - roleId=role_id, updateBy=page_object.update_by, updateTime=page_object.update_time - ) + role_id_dict = { + 'roleId': role_id, + 'updateBy': page_object.update_by, + 'updateTime': page_object.update_time, + } await RoleDao.delete_role_menu_dao(query_db, RoleMenuModel(**role_id_dict)) await RoleDao.delete_role_dept_dao(query_db, RoleDeptModel(**role_id_dict)) await RoleDao.delete_role_dao(query_db, RoleModel(**role_id_dict)) @@ -258,7 +259,7 @@ class RoleService: raise ServiceException(message='传入角色id为空') @classmethod - async def role_detail_services(cls, query_db: AsyncSession, role_id: int): + async def role_detail_services(cls, query_db: AsyncSession, role_id: int) -> RoleModel: """ 获取角色详细信息service @@ -267,15 +268,12 @@ class RoleService: :return: 角色id对应的信息 """ role = await RoleDao.get_role_detail_by_id(query_db, role_id=role_id) - if role: - result = RoleModel(**CamelCaseUtil.transform_result(role)) - else: - result = RoleModel(**dict()) + result = RoleModel(**CamelCaseUtil.transform_result(role)) if role else RoleModel() return result @staticmethod - async def export_role_list_services(role_list: List): + async def export_role_list_services(role_list: list) -> bytes: """ 导出角色列表信息service @@ -308,7 +306,7 @@ class RoleService: @classmethod async def get_role_user_allocated_list_services( cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> PageResponseModel: """ 根据角色id获取已分配用户列表 @@ -333,7 +331,7 @@ class RoleService: @classmethod async def get_role_user_unallocated_list_services( cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> PageResponseModel: """ 根据角色id获取未分配用户列表 diff --git a/ruoyi-fastapi-backend/module_admin/service/server_service.py b/ruoyi-fastapi-backend/module_admin/service/server_service.py index 2f9a53f..7bfca70 100644 --- a/ruoyi-fastapi-backend/module_admin/service/server_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/server_service.py @@ -1,8 +1,10 @@ import os import platform -import psutil import socket import time + +import psutil + from module_admin.entity.vo.server_vo import CpuInfo, MemoryInfo, PyInfo, ServerMonitorModel, SysFiles, SysInfo from utils.common_util import bytes2human @@ -13,7 +15,7 @@ class ServerService: """ @staticmethod - async def get_server_monitor_info(): + async def get_server_monitor_info() -> ServerMonitorModel: # CPU信息 # 获取CPU总核心数 cpu_num = psutil.cpu_count(logical=True) diff --git a/ruoyi-fastapi-backend/module_admin/service/user_service.py b/ruoyi-fastapi-backend/module_admin/service/user_service.py index 60f77c6..fe2bf8e 100644 --- a/ruoyi-fastapi-backend/module_admin/service/user_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/user_service.py @@ -1,12 +1,15 @@ import io -import pandas as pd from datetime import datetime +from typing import Any, Union + +import pandas as pd from fastapi import Request, UploadFile from sqlalchemy.ext.asyncio import AsyncSession -from typing import List, Union + from config.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.user_dao import UserDao +from module_admin.entity.do.user_do import SysUserRole from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.post_vo import PostPageQueryModel from module_admin.entity.vo.user_vo import ( @@ -45,7 +48,7 @@ class UserService: @classmethod async def get_user_list_services( cls, query_db: AsyncSession, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取用户列表信息service @@ -71,7 +74,7 @@ class UserService: return user_list_result @classmethod - async def check_user_allowed_services(cls, check_user: UserModel): + async def check_user_allowed_services(cls, check_user: UserModel) -> CrudResponseModel: """ 校验用户是否允许操作service @@ -80,11 +83,12 @@ class UserService: """ if check_user.admin: raise ServiceException(message='不允许操作超级管理员用户') - else: - return CrudResponseModel(is_success=True, message='校验通过') + return CrudResponseModel(is_success=True, message='校验通过') @classmethod - async def check_user_data_scope_services(cls, query_db: AsyncSession, user_id: int, data_scope_sql: str): + async def check_user_data_scope_services( + cls, query_db: AsyncSession, user_id: int, data_scope_sql: str + ) -> CrudResponseModel: """ 校验用户数据权限service @@ -96,11 +100,10 @@ class UserService: users = await UserDao.get_user_list(query_db, UserPageQueryModel(userId=user_id), data_scope_sql, is_page=False) if users: return CrudResponseModel(is_success=True, message='校验通过') - else: - raise ServiceException(message='没有权限访问用户数据') + raise ServiceException(message='没有权限访问用户数据') @classmethod - async def check_user_name_unique_services(cls, query_db: AsyncSession, page_object: UserModel): + async def check_user_name_unique_services(cls, query_db: AsyncSession, page_object: UserModel) -> bool: """ 校验用户名是否唯一service @@ -115,7 +118,7 @@ class UserService: return CommonConstant.UNIQUE @classmethod - async def check_phonenumber_unique_services(cls, query_db: AsyncSession, page_object: UserModel): + async def check_phonenumber_unique_services(cls, query_db: AsyncSession, page_object: UserModel) -> bool: """ 校验用户手机号是否唯一service @@ -130,7 +133,7 @@ class UserService: return CommonConstant.UNIQUE @classmethod - async def check_email_unique_services(cls, query_db: AsyncSession, page_object: UserModel): + async def check_email_unique_services(cls, query_db: AsyncSession, page_object: UserModel) -> bool: """ 校验用户邮箱是否唯一service @@ -145,7 +148,7 @@ class UserService: return CommonConstant.UNIQUE @classmethod - async def add_user_services(cls, query_db: AsyncSession, page_object: AddUserModel): + async def add_user_services(cls, query_db: AsyncSession, page_object: AddUserModel) -> CrudResponseModel: """ 新增用户信息service @@ -156,28 +159,43 @@ class UserService: add_user = UserModel(**page_object.model_dump(by_alias=True)) if not await cls.check_user_name_unique_services(query_db, page_object): raise ServiceException(message=f'新增用户{page_object.user_name}失败,登录账号已存在') - elif page_object.phonenumber and not await cls.check_phonenumber_unique_services(query_db, page_object): + if page_object.phonenumber and not await cls.check_phonenumber_unique_services(query_db, page_object): raise ServiceException(message=f'新增用户{page_object.user_name}失败,手机号码已存在') - elif page_object.email and not await cls.check_email_unique_services(query_db, page_object): + if page_object.email and not await cls.check_email_unique_services(query_db, page_object): raise ServiceException(message=f'新增用户{page_object.user_name}失败,邮箱账号已存在') - else: - try: - add_result = await UserDao.add_user_dao(query_db, add_user) - user_id = add_result.user_id - if page_object.role_ids: - for role in page_object.role_ids: - await UserDao.add_user_role_dao(query_db, UserRoleModel(userId=user_id, roleId=role)) - if page_object.post_ids: - for post in page_object.post_ids: - await UserDao.add_user_post_dao(query_db, UserPostModel(userId=user_id, postId=post)) - await query_db.commit() - return CrudResponseModel(is_success=True, message='新增成功') - except Exception as e: - await query_db.rollback() - raise e + try: + add_result = await UserDao.add_user_dao(query_db, add_user) + user_id = add_result.user_id + if page_object.role_ids: + for role in page_object.role_ids: + await UserDao.add_user_role_dao(query_db, UserRoleModel(userId=user_id, roleId=role)) + if page_object.post_ids: + for post in page_object.post_ids: + await UserDao.add_user_post_dao(query_db, UserPostModel(userId=user_id, postId=post)) + await query_db.commit() + return CrudResponseModel(is_success=True, message='新增成功') + except Exception as e: + await query_db.rollback() + raise e @classmethod - async def edit_user_services(cls, query_db: AsyncSession, page_object: EditUserModel): + def _deal_edit_user(cls, page_object: EditUserModel, edit_user: dict[str, Any]) -> None: + """ + 处理编辑用户字典 + + :param page_object: 编辑用户对象 + :param edit_user: 编辑用户字典 + :return: None + """ + if page_object.type not in ['status', 'avatar', 'pwd']: + del edit_user['role_ids'] + del edit_user['post_ids'] + del edit_user['role'] + else: + del edit_user['type'] + + @classmethod + async def edit_user_services(cls, query_db: AsyncSession, page_object: EditUserModel) -> CrudResponseModel: """ 编辑用户信息service @@ -186,24 +204,19 @@ class UserService: :return: 编辑用户校验结果 """ edit_user = page_object.model_dump(exclude_unset=True, exclude={'admin'}) - if page_object.type != 'status' and page_object.type != 'avatar' and page_object.type != 'pwd': - del edit_user['role_ids'] - del edit_user['post_ids'] - del edit_user['role'] - if page_object.type == 'status' or page_object.type == 'avatar' or page_object.type == 'pwd': - del edit_user['type'] + cls._deal_edit_user(page_object, edit_user) user_info = await cls.user_detail_services(query_db, edit_user.get('user_id')) if user_info.data and user_info.data.user_id: - if page_object.type != 'status' and page_object.type != 'avatar' and page_object.type != 'pwd': + if page_object.type not in ['status', 'avatar', 'pwd']: if not await cls.check_user_name_unique_services(query_db, page_object): raise ServiceException(message=f'修改用户{page_object.user_name}失败,登录账号已存在') - elif page_object.phonenumber and not await cls.check_phonenumber_unique_services(query_db, page_object): + if page_object.phonenumber and not await cls.check_phonenumber_unique_services(query_db, page_object): raise ServiceException(message=f'修改用户{page_object.user_name}失败,手机号码已存在') - elif page_object.email and not await cls.check_email_unique_services(query_db, page_object): + if page_object.email and not await cls.check_email_unique_services(query_db, page_object): raise ServiceException(message=f'修改用户{page_object.user_name}失败,邮箱账号已存在') try: await UserDao.edit_user_dao(query_db, edit_user) - if page_object.type != 'status' and page_object.type != 'avatar' and page_object.type != 'pwd': + if page_object.type not in {'status', 'avatar', 'pwd'}: await UserDao.delete_user_role_dao(query_db, UserRoleModel(userId=page_object.user_id)) await UserDao.delete_user_post_dao(query_db, UserPostModel(userId=page_object.user_id)) if page_object.role_ids: @@ -225,7 +238,7 @@ class UserService: raise ServiceException(message='用户不存在') @classmethod - async def delete_user_services(cls, query_db: AsyncSession, page_object: DeleteUserModel): + async def delete_user_services(cls, query_db: AsyncSession, page_object: DeleteUserModel) -> CrudResponseModel: """ 删除用户信息service @@ -237,9 +250,11 @@ class UserService: user_id_list = page_object.user_ids.split(',') try: for user_id in user_id_list: - user_id_dict = dict( - userId=user_id, updateBy=page_object.update_by, updateTime=page_object.update_time - ) + user_id_dict = { + 'userId': user_id, + 'updateBy': page_object.update_by, + 'updateTime': page_object.update_time, + } await UserDao.delete_user_role_dao(query_db, UserRoleModel(**user_id_dict)) await UserDao.delete_user_post_dao(query_db, UserPostModel(**user_id_dict)) await UserDao.delete_user_dao(query_db, UserModel(**user_id_dict)) @@ -252,7 +267,7 @@ class UserService: raise ServiceException(message='传入用户id为空') @classmethod - async def user_detail_services(cls, query_db: AsyncSession, user_id: Union[int, str]): + async def user_detail_services(cls, query_db: AsyncSession, user_id: Union[int, str]) -> UserDetailModel: """ 获取用户详细信息service @@ -260,7 +275,7 @@ class UserService: :param user_id: 用户id :return: 用户id对应的信息 """ - posts = await PostService.get_post_list_services(query_db, PostPageQueryModel(**{}), is_page=False) + posts = await PostService.get_post_list_services(query_db, PostPageQueryModel(), is_page=False) roles = await RoleService.get_role_select_option_services(query_db) if user_id != '': query_user = await UserDao.get_user_detail_by_id(query_db, user_id=user_id) @@ -286,7 +301,7 @@ class UserService: return UserDetailModel(posts=posts, roles=roles) @classmethod - async def user_profile_services(cls, query_db: AsyncSession, user_id: int): + async def user_profile_services(cls, query_db: AsyncSession, user_id: int) -> UserProfileModel: """ 获取用户个人详细信息service @@ -313,7 +328,7 @@ class UserService: ) @classmethod - async def reset_user_services(cls, query_db: AsyncSession, page_object: ResetUserModel): + async def reset_user_services(cls, query_db: AsyncSession, page_object: ResetUserModel) -> CrudResponseModel: """ 重置用户密码service @@ -326,10 +341,9 @@ class UserService: user = (await UserDao.get_user_detail_by_id(query_db, user_id=page_object.user_id)).get('user_basic_info') if not PwdUtil.verify_password(page_object.old_password, user.password): raise ServiceException(message='修改密码失败,旧密码错误') - elif PwdUtil.verify_password(page_object.password, user.password): + if PwdUtil.verify_password(page_object.password, user.password): raise ServiceException(message='新密码不能与旧密码相同') - else: - del reset_user['old_password'] + del reset_user['old_password'] if page_object.sms_code and page_object.session_id: del reset_user['sms_code'] del reset_user['session_id'] @@ -342,6 +356,34 @@ class UserService: await query_db.rollback() raise e + @classmethod + def _set_row_sex_value(cls, row: pd.Series) -> None: + """ + 设置行性别值 + + :param row: 行数据 + :return: None + """ + if row['sex'] == '男': + row['sex'] = '0' + if row['sex'] == '女': + row['sex'] = '1' + if row['sex'] == '未知': + row['sex'] = '2' + + @classmethod + def _set_row_status_value(cls, row: pd.Series) -> None: + """ + 设置行状态值 + + :param row: 行数据 + :return: None + """ + if row['status'] == '正常': + row['status'] = '0' + if row['status'] == '停用': + row['status'] = '1' + @classmethod async def batch_import_user_services( cls, @@ -352,7 +394,7 @@ class UserService: current_user: CurrentUserModel, user_data_scope_sql: str, dept_data_scope_sql: str, - ): + ) -> CrudResponseModel: """ 批量导入用户service @@ -381,18 +423,10 @@ class UserService: add_error_result = [] count = 0 try: - for index, row in df.iterrows(): + for _index, row in df.iterrows(): count = count + 1 - if row['sex'] == '男': - row['sex'] = '0' - if row['sex'] == '女': - row['sex'] = '1' - if row['sex'] == '未知': - row['sex'] = '2' - if row['status'] == '正常': - row['status'] = '0' - if row['status'] == '停用': - row['status'] = '1' + cls._set_row_sex_value(row) + cls._set_row_status_value(row) add_user = UserModel( deptId=row['dept_id'], userName=row['user_name'], @@ -438,7 +472,7 @@ class UserService: edit_user = edit_user_model.model_dump(exclude_unset=True) await UserDao.edit_user_dao(query_db, edit_user) else: - add_error_result.append(f"{count}.用户账号{row['user_name']}已存在") + add_error_result.append(f'{count}.用户账号{row["user_name"]}已存在') else: add_user.validate_fields() if not current_user.user.admin: @@ -453,7 +487,7 @@ class UserService: raise e @staticmethod - async def get_user_import_template_services(): + async def get_user_import_template_services() -> bytes: """ 获取用户导入模板service @@ -469,7 +503,7 @@ class UserService: return binary_data @staticmethod - async def export_user_list_services(user_list: List): + async def export_user_list_services(user_list: list) -> bytes: """ 导出用户信息service @@ -510,7 +544,9 @@ class UserService: return binary_data @classmethod - async def get_user_role_allocated_list_services(cls, query_db: AsyncSession, page_object: UserRoleQueryModel): + async def get_user_role_allocated_list_services( + cls, query_db: AsyncSession, page_object: UserRoleQueryModel + ) -> UserRoleResponseModel: """ 根据用户id获取已分配角色列表 @@ -540,7 +576,7 @@ class UserService: return result @classmethod - async def add_user_role_services(cls, query_db: AsyncSession, page_object: CrudUserRoleModel): + async def add_user_role_services(cls, query_db: AsyncSession, page_object: CrudUserRoleModel) -> CrudResponseModel: """ 新增用户关联角色信息service @@ -576,10 +612,7 @@ class UserService: ) if user_role: continue - else: - await UserDao.add_user_role_dao( - query_db, UserRoleModel(userId=user_id, roleId=page_object.role_id) - ) + await UserDao.add_user_role_dao(query_db, UserRoleModel(userId=user_id, roleId=page_object.role_id)) await query_db.commit() return CrudResponseModel(is_success=True, message='新增成功') except Exception as e: @@ -589,7 +622,9 @@ class UserService: raise ServiceException(message='不满足新增条件') @classmethod - async def delete_user_role_services(cls, query_db: AsyncSession, page_object: CrudUserRoleModel): + async def delete_user_role_services( + cls, query_db: AsyncSession, page_object: CrudUserRoleModel + ) -> CrudResponseModel: """ 删除用户关联角色信息service @@ -626,7 +661,9 @@ class UserService: raise ServiceException(message='传入用户角色关联信息为空') @classmethod - async def detail_user_role_services(cls, query_db: AsyncSession, page_object: UserRoleModel): + async def detail_user_role_services( + cls, query_db: AsyncSession, page_object: UserRoleModel + ) -> Union[SysUserRole, None]: """ 获取用户关联角色详细信息service diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index 4e227c1..9a22bc8 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -1,14 +1,17 @@ from datetime import datetime -from fastapi import APIRouter, Depends, Query, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.env import GenConfig from config.get_db import get_db from module_admin.annotation.log_annotation import Log from module_admin.aspect.interface_auth import CheckRoleInterfaceAuth, CheckUserInterfaceAuth -from module_admin.service.login_service import LoginService from module_admin.entity.vo.user_vo import CurrentUserModel +from module_admin.service.login_service import LoginService from module_generator.entity.vo.gen_vo import DeleteGenTableModel, EditGenTableModel, GenTablePageQueryModel from module_generator.service.gen_service import GenTableColumnService, GenTableService from utils.common_util import bytes2file_response @@ -16,18 +19,17 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil - -genController = APIRouter(prefix='/tool/gen', dependencies=[Depends(LoginService.get_current_user)]) +gen_controller = APIRouter(prefix='/tool/gen', dependencies=[Depends(LoginService.get_current_user)]) -@genController.get( +@gen_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:list'))] ) async def get_gen_table_list( request: Request, - gen_page_query: GenTablePageQueryModel = Depends(GenTablePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + gen_page_query: Annotated[GenTablePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 gen_page_query_result = await GenTableService.get_gen_table_list_services(query_db, gen_page_query, is_page=True) logger.info('获取成功') @@ -35,14 +37,14 @@ async def get_gen_table_list( return ResponseUtil.success(model_content=gen_page_query_result) -@genController.get( +@gen_controller.get( '/db/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:list'))] ) async def get_gen_db_table_list( request: Request, - gen_page_query: GenTablePageQueryModel = Depends(GenTablePageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + gen_page_query: Annotated[GenTablePageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取分页数据 gen_page_query_result = await GenTableService.get_gen_db_table_list_services(query_db, gen_page_query, is_page=True) logger.info('获取成功') @@ -50,14 +52,14 @@ async def get_gen_db_table_list( return ResponseUtil.success(model_content=gen_page_query_result) -@genController.post('/importTable', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:import'))]) +@gen_controller.post('/importTable', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:import'))]) @Log(title='代码生成', business_type=BusinessType.IMPORT) async def import_gen_table( request: Request, - tables: str = Query(), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + tables: Annotated[str, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: table_names = tables.split(',') if tables else [] add_gen_table_list = await GenTableService.get_gen_db_table_list_by_name_services(query_db, table_names) add_gen_table_result = await GenTableService.import_gen_table_services(query_db, add_gen_table_list, current_user) @@ -66,15 +68,15 @@ async def import_gen_table( return ResponseUtil.success(msg=add_gen_table_result.message) -@genController.put('', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:edit'))]) +@gen_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:edit'))]) @ValidateFields(validate_model='edit_gen_table') @Log(title='代码生成', business_type=BusinessType.UPDATE) async def edit_gen_table( request: Request, edit_gen_table: EditGenTableModel, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: edit_gen_table.update_by = current_user.user.user_name edit_gen_table.update_time = datetime.now() await GenTableService.validate_edit(edit_gen_table) @@ -84,9 +86,13 @@ async def edit_gen_table( return ResponseUtil.success(msg=edit_gen_result.message) -@genController.delete('/{table_ids}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:remove'))]) +@gen_controller.delete('/{table_ids}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:remove'))]) @Log(title='代码生成', business_type=BusinessType.DELETE) -async def delete_gen_table(request: Request, table_ids: str, query_db: AsyncSession = Depends(get_db)): +async def delete_gen_table( + request: Request, + table_ids: Annotated[str, Path(description='需要删除的代码生成业务表ID')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_gen_table = DeleteGenTableModel(tableIds=table_ids) delete_gen_table_result = await GenTableService.delete_gen_table_services(query_db, delete_gen_table) logger.info(delete_gen_table_result.message) @@ -94,23 +100,27 @@ async def delete_gen_table(request: Request, table_ids: str, query_db: AsyncSess return ResponseUtil.success(msg=delete_gen_table_result.message) -@genController.post('/createTable', dependencies=[Depends(CheckRoleInterfaceAuth('admin'))]) +@gen_controller.post('/createTable', dependencies=[Depends(CheckRoleInterfaceAuth('admin'))]) @Log(title='创建表', business_type=BusinessType.OTHER) async def create_table( request: Request, - sql: str = Query(), - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + sql: Annotated[str, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: create_table_result = await GenTableService.create_table_services(query_db, sql, current_user) logger.info(create_table_result.message) return ResponseUtil.success(msg=create_table_result.message) -@genController.get('/batchGenCode', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:code'))]) +@gen_controller.get('/batchGenCode', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:code'))]) @Log(title='代码生成', business_type=BusinessType.GENCODE) -async def batch_gen_code(request: Request, tables: str = Query(), query_db: AsyncSession = Depends(get_db)): +async def batch_gen_code( + request: Request, + tables: Annotated[str, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: table_names = tables.split(',') if tables else [] batch_gen_code_result = await GenTableService.batch_gen_code_services(query_db, table_names) logger.info('生成代码成功') @@ -118,9 +128,13 @@ async def batch_gen_code(request: Request, tables: str = Query(), query_db: Asyn return ResponseUtil.streaming(data=bytes2file_response(batch_gen_code_result)) -@genController.get('/genCode/{table_name}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:code'))]) +@gen_controller.get('/genCode/{table_name}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:code'))]) @Log(title='代码生成', business_type=BusinessType.GENCODE) -async def gen_code_local(request: Request, table_name: str, query_db: AsyncSession = Depends(get_db)): +async def gen_code_local( + request: Request, + table_name: Annotated[str, Path(description='表名称')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: if not GenConfig.allow_overwrite: logger.error('【系统预设】不允许生成文件覆盖到本地') return ResponseUtil.error('【系统预设】不允许生成文件覆盖到本地') @@ -130,28 +144,40 @@ async def gen_code_local(request: Request, table_name: str, query_db: AsyncSessi return ResponseUtil.success(msg=gen_code_local_result.message) -@genController.get('/{table_id}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:query'))]) -async def query_detail_gen_table(request: Request, table_id: int, query_db: AsyncSession = Depends(get_db)): +@gen_controller.get('/{table_id}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:query'))]) +async def query_detail_gen_table( + request: Request, + table_id: Annotated[int, Path(description='表编号')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: gen_table = await GenTableService.get_gen_table_by_id_services(query_db, table_id) gen_tables = await GenTableService.get_gen_table_all_services(query_db) gen_columns = await GenTableColumnService.get_gen_table_column_list_by_table_id_services(query_db, table_id) - gen_table_detail_result = dict(info=gen_table, rows=gen_columns, tables=gen_tables) + gen_table_detail_result = {'info': gen_table, 'rows': gen_columns, 'tables': gen_tables} logger.info(f'获取table_id为{table_id}的信息成功') return ResponseUtil.success(data=gen_table_detail_result) -@genController.get('/preview/{table_id}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:preview'))]) -async def preview_code(request: Request, table_id: int, query_db: AsyncSession = Depends(get_db)): +@gen_controller.get('/preview/{table_id}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:preview'))]) +async def preview_code( + request: Request, + table_id: Annotated[int, Path(description='表编号')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: preview_code_result = await GenTableService.preview_code_services(query_db, table_id) logger.info('获取预览代码成功') return ResponseUtil.success(data=preview_code_result) -@genController.get('/synchDb/{table_name}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:edit'))]) +@gen_controller.get('/synchDb/{table_name}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:edit'))]) @Log(title='代码生成', business_type=BusinessType.UPDATE) -async def sync_db(request: Request, table_name: str, query_db: AsyncSession = Depends(get_db)): +async def sync_db( + request: Request, + table_name: Annotated[str, Path(description='表名称')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: sync_db_result = await GenTableService.sync_db_services(query_db, table_name) logger.info(sync_db_result.message) diff --git a/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py b/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py index 937668a..ae4fc9b 100644 --- a/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py +++ b/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py @@ -1,9 +1,12 @@ +from collections.abc import Sequence from datetime import datetime, time -from sqlalchemy import delete, func, select, text, update +from typing import Any, Union + +from sqlalchemy import Row, delete, func, select, text, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from sqlglot.expressions import Expression -from typing import List + from config.env import DataBaseConfig from module_generator.entity.do.gen_do import GenTable, GenTableColumn from module_generator.entity.vo.gen_vo import ( @@ -13,7 +16,7 @@ from module_generator.entity.vo.gen_vo import ( GenTableModel, GenTablePageQueryModel, ) -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class GenTableDao: @@ -22,7 +25,7 @@ class GenTableDao: """ @classmethod - async def get_gen_table_by_id(cls, db: AsyncSession, table_id: int): + async def get_gen_table_by_id(cls, db: AsyncSession, table_id: int) -> Union[GenTable, None]: """ 根据业务表id获取需要生成的业务表信息 @@ -43,7 +46,7 @@ class GenTableDao: return gen_table_info @classmethod - async def get_gen_table_by_name(cls, db: AsyncSession, table_name: str): + async def get_gen_table_by_name(cls, db: AsyncSession, table_name: str) -> Union[GenTable, None]: """ 根据业务表名称获取需要生成的业务表信息 @@ -64,7 +67,7 @@ class GenTableDao: return gen_table_info @classmethod - async def get_gen_table_all(cls, db: AsyncSession): + async def get_gen_table_all(cls, db: AsyncSession) -> Sequence[GenTable]: """ 获取所有业务表信息 @@ -76,7 +79,7 @@ class GenTableDao: return gen_table_all @classmethod - async def create_table_by_sql_dao(cls, db: AsyncSession, sql_statements: List[Expression]): + async def create_table_by_sql_dao(cls, db: AsyncSession, sql_statements: list[Expression]) -> None: """ 根据sql语句创建表结构 @@ -89,7 +92,9 @@ class GenTableDao: await db.execute(text(sql)) @classmethod - async def get_gen_table_list(cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False): + async def get_gen_table_list( + cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取代码生成业务表列表信息 @@ -117,12 +122,16 @@ class GenTableDao: ) .distinct() ) - gen_table_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + gen_table_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return gen_table_list @classmethod - async def get_gen_db_table_list(cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False): + async def get_gen_db_table_list( + cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取数据库列表信息 @@ -133,28 +142,28 @@ class GenTableDao: """ if DataBaseConfig.db_type == 'postgresql': query_sql = """ - table_name as table_name, - table_comment as table_comment, - create_time as create_time, + table_name as table_name, + table_comment as table_comment, + create_time as create_time, update_time as update_time - from + from list_table - where - table_name not like 'apscheduler_%' + where + table_name not like 'apscheduler_%' and table_name not like 'gen_%' and table_name not in (select table_name from gen_table) """ else: - query_sql = """ - table_name as table_name, - table_comment as table_comment, - create_time as create_time, + query_sql = r""" + table_name as table_name, + table_comment as table_comment, + create_time as create_time, update_time as update_time - from + from information_schema.tables - where + where table_schema = (select database()) - and table_name not like 'apscheduler\_%' + and table_name not like 'apscheduler\_%' and table_name not like 'gen\_%' and table_name not in (select table_name from gen_table) """ @@ -174,19 +183,16 @@ class GenTableDao: query_sql += """and date_format(create_time, '%Y%m%d') >= date_format(:end_time, '%Y%m%d')""" query_sql += """order by create_time desc""" query = select( - text(query_sql).bindparams( - **{ - k: v - for k, v in query_object.model_dump(exclude_none=True, exclude={'page_num', 'page_size'}).items() - } - ) + text(query_sql).bindparams(**query_object.model_dump(exclude_none=True, exclude={'page_num', 'page_size'})) + ) + gen_db_table_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page ) - gen_db_table_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) return gen_db_table_list @classmethod - async def get_gen_db_table_list_by_names(cls, db: AsyncSession, table_names: List[str]): + async def get_gen_db_table_list_by_names(cls, db: AsyncSession, table_names: list[str]) -> Sequence[Row]: """ 根据业务表名称组获取数据库列表信息 @@ -197,29 +203,29 @@ class GenTableDao: if DataBaseConfig.db_type == 'postgresql': query_sql = """ select - table_name as table_name, - table_comment as table_comment, - create_time as create_time, - update_time as update_time - from + table_name as table_name, + table_comment as table_comment, + create_time as create_time, + update_time as update_time + from list_table - where - table_name not like 'qrtz_%' - and table_name not like 'gen_%' + where + table_name not like 'qrtz_%' + and table_name not like 'gen_%' and table_name = any(:table_names) """ else: - query_sql = """ + query_sql = r""" select - table_name as table_name, - table_comment as table_comment, - create_time as create_time, - update_time as update_time - from + table_name as table_name, + table_comment as table_comment, + create_time as create_time, + update_time as update_time + from information_schema.tables - where - table_name not like 'qrtz\_%' - and table_name not like 'gen\_%' + where + table_name not like 'qrtz\_%' + and table_name not like 'gen\_%' and table_schema = (select database()) and table_name in :table_names """ @@ -229,7 +235,7 @@ class GenTableDao: return gen_db_table_list @classmethod - async def add_gen_table_dao(cls, db: AsyncSession, gen_table: GenTableModel): + async def add_gen_table_dao(cls, db: AsyncSession, gen_table: GenTableModel) -> GenTable: """ 新增业务表数据库操作 @@ -244,7 +250,7 @@ class GenTableDao: return db_gen_table @classmethod - async def edit_gen_table_dao(cls, db: AsyncSession, gen_table: dict): + async def edit_gen_table_dao(cls, db: AsyncSession, gen_table: dict) -> None: """ 编辑业务表数据库操作 @@ -255,7 +261,7 @@ class GenTableDao: await db.execute(update(GenTable), [GenTableBaseModel(**gen_table).model_dump()]) @classmethod - async def delete_gen_table_dao(cls, db: AsyncSession, gen_table: GenTableModel): + async def delete_gen_table_dao(cls, db: AsyncSession, gen_table: GenTableModel) -> None: """ 删除业务表数据库操作 @@ -272,7 +278,7 @@ class GenTableColumnDao: """ @classmethod - async def get_gen_table_column_list_by_table_id(cls, db: AsyncSession, table_id: int): + async def get_gen_table_column_list_by_table_id(cls, db: AsyncSession, table_id: int) -> GenTableColumn: """ 根据业务表id获取需要生成的业务表字段列表信息 @@ -293,7 +299,7 @@ class GenTableColumnDao: return gen_table_column_list @classmethod - async def get_gen_db_table_columns_by_name(cls, db: AsyncSession, table_name: str): + async def get_gen_db_table_columns_by_name(cls, db: AsyncSession, table_name: str) -> Sequence[Row]: """ 根据业务表名称获取业务表字段列表信息 @@ -312,29 +318,29 @@ class GenTableColumnDao: """ else: query_sql = """ - select + select column_name as column_name, - case - when is_nullable = 'no' and column_key != 'PRI' then '1' - else '0' + case + when is_nullable = 'no' and column_key != 'PRI' then '1' + else '0' end as is_required, - case - when column_key = 'PRI' then '1' - else '0' + case + when column_key = 'PRI' then '1' + else '0' end as is_pk, ordinal_position as sort, column_comment as column_comment, - case - when extra = 'auto_increment' then '1' - else '0' + case + when extra = 'auto_increment' then '1' + else '0' end as is_increment, column_type as column_type - from + from information_schema.columns - where - table_schema = (select database()) + where + table_schema = (select database()) and table_name = :table_name - order by + order by ordinal_position """ query = text(query_sql).bindparams(table_name=table_name) @@ -343,7 +349,7 @@ class GenTableColumnDao: return gen_db_table_columns @classmethod - async def add_gen_table_column_dao(cls, db: AsyncSession, gen_table_column: GenTableColumnModel): + async def add_gen_table_column_dao(cls, db: AsyncSession, gen_table_column: GenTableColumnModel) -> GenTableColumn: """ 新增业务表字段数据库操作 @@ -360,7 +366,7 @@ class GenTableColumnDao: return db_gen_table_column @classmethod - async def edit_gen_table_column_dao(cls, db: AsyncSession, gen_table_column: dict): + async def edit_gen_table_column_dao(cls, db: AsyncSession, gen_table_column: dict) -> None: """ 编辑业务表字段数据库操作 @@ -371,7 +377,9 @@ class GenTableColumnDao: await db.execute(update(GenTableColumn), [GenTableColumnBaseModel(**gen_table_column).model_dump()]) @classmethod - async def delete_gen_table_column_by_table_id_dao(cls, db: AsyncSession, gen_table_column: GenTableColumnModel): + async def delete_gen_table_column_by_table_id_dao( + cls, db: AsyncSession, gen_table_column: GenTableColumnModel + ) -> None: """ 通过业务表id删除业务表字段数据库操作 @@ -382,7 +390,9 @@ class GenTableColumnDao: await db.execute(delete(GenTableColumn).where(GenTableColumn.table_id.in_([gen_table_column.table_id]))) @classmethod - async def delete_gen_table_column_by_column_id_dao(cls, db: AsyncSession, gen_table_column: GenTableColumnModel): + async def delete_gen_table_column_by_column_id_dao( + cls, db: AsyncSession, gen_table_column: GenTableColumnModel + ) -> None: """ 通过业务字段id删除业务表字段数据库操作 diff --git a/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py b/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py index edd62f6..6f9e020 100644 --- a/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py +++ b/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py @@ -1,6 +1,8 @@ from datetime import datetime -from sqlalchemy import BigInteger, CHAR, Column, DateTime, ForeignKey, Integer, String + +from sqlalchemy import CHAR, BigInteger, Column, DateTime, ForeignKey, Integer, String from sqlalchemy.orm import relationship + from config.database import Base from config.env import DataBaseConfig from utils.common_util import SqlalchemyUtil diff --git a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py index e5d7917..d821287 100644 --- a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py +++ b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py @@ -1,10 +1,11 @@ from datetime import datetime +from typing import Literal, Optional, Union + from pydantic import BaseModel, ConfigDict, Field, model_validator from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank -from typing import List, Literal, Optional + from config.constant import GenConstant -from module_admin.annotation.pydantic_annotation import as_query from utils.string_util import StringUtil @@ -38,38 +39,38 @@ class GenTableBaseModel(BaseModel): remark: Optional[str] = Field(default=None, description='备注') @NotBlank(field_name='table_name', message='表名称不能为空') - def get_table_name(self): + def get_table_name(self) -> Union[str, None]: return self.table_name @NotBlank(field_name='table_comment', message='表描述不能为空') - def get_table_comment(self): + def get_table_comment(self) -> Union[str, None]: return self.table_comment @NotBlank(field_name='class_name', message='实体类名称不能为空') - def get_class_name(self): + def get_class_name(self) -> Union[str, None]: return self.class_name @NotBlank(field_name='package_name', message='生成包路径不能为空') - def get_package_name(self): + def get_package_name(self) -> Union[str, None]: return self.package_name @NotBlank(field_name='module_name', message='生成模块名不能为空') - def get_module_name(self): + def get_module_name(self) -> Union[str, None]: return self.module_name @NotBlank(field_name='business_name', message='生成业务名不能为空') - def get_business_name(self): + def get_business_name(self) -> Union[str, None]: return self.business_name @NotBlank(field_name='function_name', message='生成功能名不能为空') - def get_function_name(self): + def get_function_name(self) -> Union[str, None]: return self.function_name @NotBlank(field_name='function_author', message='生成功能作者不能为空') - def get_function_author(self): + def get_function_author(self) -> Union[str, None]: return self.function_author - def validate_fields(self): + def validate_fields(self) -> None: self.get_table_name() self.get_table_comment() self.get_class_name() @@ -87,7 +88,7 @@ class GenTableModel(GenTableBaseModel): pk_column: Optional['GenTableColumnModel'] = Field(default=None, description='主键信息') sub_table: Optional['GenTableModel'] = Field(default=None, description='子表信息') - columns: Optional[List['GenTableColumnModel']] = Field(default=None, description='表列信息') + columns: Optional[list['GenTableColumnModel']] = Field(default=None, description='表列信息') tree_code: Optional[str] = Field(default=None, description='树编码字段') tree_parent_code: Optional[str] = Field(default=None, description='树父编码字段') tree_name: Optional[str] = Field(default=None, description='树名称字段') @@ -99,9 +100,9 @@ class GenTableModel(GenTableBaseModel): @model_validator(mode='after') def check_some_is(self) -> 'GenTableModel': - self.sub = True if self.tpl_category and self.tpl_category == GenConstant.TPL_SUB else False - self.tree = True if self.tpl_category and self.tpl_category == GenConstant.TPL_TREE else False - self.crud = True if self.tpl_category and self.tpl_category == GenConstant.TPL_CRUD else False + self.sub = bool(self.tpl_category and self.tpl_category == GenConstant.TPL_SUB) + self.tree = bool(self.tpl_category and self.tpl_category == GenConstant.TPL_TREE) + self.crud = bool(self.tpl_category and self.tpl_category == GenConstant.TPL_CRUD) return self @@ -135,7 +136,6 @@ class GenTableQueryModel(GenTableBaseModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class GenTablePageQueryModel(GenTableQueryModel): """ 代码生成业务表分页查询模型 @@ -189,10 +189,10 @@ class GenTableColumnBaseModel(BaseModel): update_time: Optional[datetime] = Field(default=None, description='更新时间') @NotBlank(field_name='python_field', message='Python属性不能为空') - def get_python_field(self): + def get_python_field(self) -> Union[str, None]: return self.python_field - def validate_fields(self): + def validate_fields(self) -> None: self.get_python_field() @@ -216,21 +216,19 @@ class GenTableColumnModel(GenTableColumnBaseModel): @model_validator(mode='after') def check_some_is(self) -> 'GenTableModel': self.cap_python_field = self.python_field[0].upper() + self.python_field[1:] if self.python_field else None - self.pk = True if self.is_pk and self.is_pk == '1' else False - self.increment = True if self.is_increment and self.is_increment == '1' else False - self.required = True if self.is_required and self.is_required == '1' else False - self.unique = True if self.is_unique and self.is_unique == '1' else False - self.insert = True if self.is_insert and self.is_insert == '1' else False - self.edit = True if self.is_edit and self.is_edit == '1' else False - self.list = True if self.is_list and self.is_list == '1' else False - self.query = True if self.is_query and self.is_query == '1' else False - self.super_column = ( - True - if StringUtil.equals_any_ignore_case(self.python_field, GenConstant.TREE_ENTITY + GenConstant.BASE_ENTITY) - else False + self.pk = self.is_pk and self.is_pk == '1' + self.increment = bool(self.is_increment and self.is_increment == '1') + self.required = bool(self.is_required and self.is_required == '1') + self.unique = bool(self.is_unique and self.is_unique == '1') + self.insert = bool(self.is_insert and self.is_insert == '1') + self.edit = bool(self.is_edit and self.is_edit == '1') + self.list = bool(self.is_list and self.is_list == '1') + self.query = bool(self.is_query and self.is_query == '1') + self.super_column = bool( + StringUtil.equals_any_ignore_case(self.python_field, GenConstant.TREE_ENTITY + GenConstant.BASE_ENTITY) ) - self.usable_column = ( - True if StringUtil.equals_any_ignore_case(self.python_field, ['parentId', 'orderNum', 'remark']) else False + self.usable_column = bool( + StringUtil.equals_any_ignore_case(self.python_field, ['parentId', 'orderNum', 'remark']) ) return self @@ -244,7 +242,6 @@ class GenTableColumnQueryModel(GenTableColumnBaseModel): end_time: Optional[str] = Field(default=None, description='结束时间') -@as_query class GenTableColumnPageQueryModel(GenTableColumnQueryModel): """ 代码生成业务表字段分页查询模型 diff --git a/ruoyi-fastapi-backend/module_generator/service/gen_service.py b/ruoyi-fastapi-backend/module_generator/service/gen_service.py index aec0bbf..a77cd85 100644 --- a/ruoyi-fastapi-backend/module_generator/service/gen_service.py +++ b/ruoyi-fastapi-backend/module_generator/service/gen_service.py @@ -3,15 +3,19 @@ import json import os import zipfile from datetime import datetime +from typing import Any, Union + +import aiofiles from sqlalchemy.ext.asyncio import AsyncSession from sqlglot import parse as sqlglot_parse from sqlglot.expressions import Add, Alter, Create, Delete, Drop, Expression, Insert, Table, TruncateTable, Update -from typing import List + from config.constant import GenConstant from config.env import DataBaseConfig, GenConfig from exceptions.exception import ServiceException from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.user_vo import CurrentUserModel +from module_generator.dao.gen_dao import GenTableColumnDao, GenTableDao from module_generator.entity.vo.gen_vo import ( DeleteGenTableModel, EditGenTableModel, @@ -19,9 +23,9 @@ from module_generator.entity.vo.gen_vo import ( GenTableModel, GenTablePageQueryModel, ) -from module_generator.dao.gen_dao import GenTableColumnDao, GenTableDao from utils.common_util import CamelCaseUtil from utils.gen_util import GenUtils +from utils.page_util import PageResponseModel from utils.template_util import TemplateInitializer, TemplateUtils @@ -33,7 +37,7 @@ class GenTableService: @classmethod async def get_gen_table_list_services( cls, query_db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取代码生成业务表列表信息service @@ -49,7 +53,7 @@ class GenTableService: @classmethod async def get_gen_db_table_list_services( cls, query_db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取数据库列表信息service @@ -63,7 +67,9 @@ class GenTableService: return gen_db_table_list_result @classmethod - async def get_gen_db_table_list_by_name_services(cls, query_db: AsyncSession, table_names: List[str]): + async def get_gen_db_table_list_by_name_services( + cls, query_db: AsyncSession, table_names: list[str] + ) -> list[GenTableModel]: """ 根据表名称组获取数据库列表信息service @@ -77,8 +83,8 @@ class GenTableService: @classmethod async def import_gen_table_services( - cls, query_db: AsyncSession, gen_table_list: List[GenTableModel], current_user: CurrentUserModel - ): + cls, query_db: AsyncSession, gen_table_list: list[GenTableModel], current_user: CurrentUserModel + ) -> CrudResponseModel: """ 导入表结构service @@ -105,10 +111,10 @@ class GenTableService: return CrudResponseModel(is_success=True, message='导入成功') except Exception as e: await query_db.rollback() - raise ServiceException(message=f'导入失败, {str(e)}') + raise ServiceException(message=f'导入失败, {e}') from e @classmethod - async def edit_gen_table_services(cls, query_db: AsyncSession, page_object: EditGenTableModel): + async def edit_gen_table_services(cls, query_db: AsyncSession, page_object: EditGenTableModel) -> CrudResponseModel: """ 编辑业务表信息service @@ -137,7 +143,9 @@ class GenTableService: raise ServiceException(message='业务表不存在') @classmethod - async def delete_gen_table_services(cls, query_db: AsyncSession, page_object: DeleteGenTableModel): + async def delete_gen_table_services( + cls, query_db: AsyncSession, page_object: DeleteGenTableModel + ) -> CrudResponseModel: """ 删除业务表信息service @@ -162,7 +170,7 @@ class GenTableService: raise ServiceException(message='传入业务表id为空') @classmethod - async def get_gen_table_by_id_services(cls, query_db: AsyncSession, table_id: int): + async def get_gen_table_by_id_services(cls, query_db: AsyncSession, table_id: int) -> GenTableModel: """ 获取需要生成的业务表详细信息service @@ -176,7 +184,7 @@ class GenTableService: return result @classmethod - async def get_gen_table_all_services(cls, query_db: AsyncSession): + async def get_gen_table_all_services(cls, query_db: AsyncSession) -> list[GenTableModel]: """ 获取所有业务表信息service @@ -189,7 +197,9 @@ class GenTableService: return result @classmethod - async def create_table_services(cls, query_db: AsyncSession, sql: str, current_user: CurrentUserModel): + async def create_table_services( + cls, query_db: AsyncSession, sql: str, current_user: CurrentUserModel + ) -> CrudResponseModel: """ 创建表结构service @@ -208,12 +218,12 @@ class GenTableService: return CrudResponseModel(is_success=True, message='创建表结构成功') except Exception as e: - raise ServiceException(message=f'创建表结构异常,详细错误信息:{str(e)}') + raise ServiceException(message=f'创建表结构异常,详细错误信息:{e}') from e else: raise ServiceException(message='建表语句不合法') @classmethod - def __is_valid_create_table(cls, sql_statements: List[Expression]): + def __is_valid_create_table(cls, sql_statements: list[Expression]) -> bool: """ 校验sql语句是否为合法的建表语句 @@ -228,26 +238,24 @@ class GenTableService: ) for sql_statement in sql_statements ] - if not any(validate_create) or any(validate_forbidden_keywords): - return False - return True + return not (not any(validate_create) or any(validate_forbidden_keywords)) @classmethod - def __get_table_names(cls, sql_statements: List[Expression]): + def __get_table_names(cls, sql_statements: list[Expression]) -> list[str]: """ 获取sql语句中所有的建表表名 :param sql_statements: sql语句的ast列表 :return: 建表表名列表 """ - table_names = [] - for sql_statement in sql_statements: - if isinstance(sql_statement, Create): - table_names.append(sql_statement.find(Table).name) + table_names = [ + sql_statement.find(Table).name for sql_statement in sql_statements if isinstance(sql_statement, Create) + ] + return table_names @classmethod - async def preview_code_services(cls, query_db: AsyncSession, table_id: int): + async def preview_code_services(cls, query_db: AsyncSession, table_id: int) -> dict[str, str]: """ 预览代码service @@ -270,7 +278,7 @@ class GenTableService: return preview_code_result @classmethod - async def generate_code_services(cls, query_db: AsyncSession, table_name: str): + async def generate_code_services(cls, query_db: AsyncSession, table_name: str) -> CrudResponseModel: """ 生成代码至指定路径service @@ -280,22 +288,20 @@ class GenTableService: """ env = TemplateInitializer.init_jinja2() render_info = await cls.__get_gen_render_info(query_db, table_name) - for template in render_info[0]: - try: + try: + for template in render_info[0]: render_content = env.get_template(template).render(**render_info[2]) gen_path = cls.__get_gen_path(render_info[3], template) os.makedirs(os.path.dirname(gen_path), exist_ok=True) - with open(gen_path, 'w', encoding='utf-8') as f: - f.write(render_content) - except Exception as e: - raise ServiceException( - message=f'渲染模板失败,表名:{render_info[3].table_name},详细错误信息:{str(e)}' - ) + async with aiofiles.open(gen_path, 'w', encoding='utf-8') as f: + await f.write(render_content) + except Exception as e: + raise ServiceException(message=f'渲染模板失败,表名:{render_info[3].table_name},详细错误信息:{e}') from e return CrudResponseModel(is_success=True, message='生成代码成功') @classmethod - async def batch_gen_code_services(cls, query_db: AsyncSession, table_names: List[str]): + async def batch_gen_code_services(cls, query_db: AsyncSession, table_names: list[str]) -> bytes: """ 批量生成代码service @@ -317,7 +323,7 @@ class GenTableService: return zip_data @classmethod - async def __get_gen_render_info(cls, query_db: AsyncSession, table_name: str): + async def __get_gen_render_info(cls, query_db: AsyncSession, table_name: str) -> list: """ 获取生成代码渲染模板相关信息 @@ -337,7 +343,7 @@ class GenTableService: return [template_list, output_files, context, gen_table] @classmethod - def __get_gen_path(cls, gen_table: GenTableModel, template: str): + def __get_gen_path(cls, gen_table: GenTableModel, template: str) -> str: """ 根据GenTableModel对象和模板名称生成路径 @@ -348,11 +354,11 @@ class GenTableService: gen_path = gen_table.gen_path if gen_path == '/': return os.path.join(os.getcwd(), GenConfig.GEN_PATH, TemplateUtils.get_file_name(template, gen_table)) - else: - return os.path.join(gen_path, TemplateUtils.get_file_name(template, gen_table)) + + return os.path.join(gen_path, TemplateUtils.get_file_name(template, gen_table)) @classmethod - async def sync_db_services(cls, query_db: AsyncSession, table_name: str): + async def sync_db_services(cls, query_db: AsyncSession, table_name: str) -> CrudResponseModel: """ 同步数据库service @@ -402,7 +408,7 @@ class GenTableService: raise e @classmethod - async def set_sub_table(cls, query_db: AsyncSession, gen_table: GenTableModel): + async def set_sub_table(cls, query_db: AsyncSession, gen_table: GenTableModel) -> None: """ 设置主子表信息 @@ -415,7 +421,7 @@ class GenTableService: gen_table.sub_table = GenTableModel(**CamelCaseUtil.transform_result(sub_table)) @classmethod - async def set_pk_column(cls, gen_table: GenTableModel): + async def set_pk_column(cls, gen_table: GenTableModel) -> None: """ 设置主键列信息 @@ -437,7 +443,7 @@ class GenTableService: gen_table.sub_table.pk_column = gen_table.sub_table.columns[0] @classmethod - async def set_table_from_options(cls, gen_table: GenTableModel): + async def set_table_from_options(cls, gen_table: GenTableModel) -> GenTableModel: """ 设置代码生成其他选项值 @@ -455,7 +461,7 @@ class GenTableService: return gen_table @classmethod - async def validate_edit(cls, edit_gen_table: EditGenTableModel): + async def validate_edit(cls, edit_gen_table: EditGenTableModel) -> None: """ 编辑保存参数校验 @@ -466,14 +472,14 @@ class GenTableService: if GenConstant.TREE_CODE not in params_obj: raise ServiceException(message='树编码字段不能为空') - elif GenConstant.TREE_PARENT_CODE not in params_obj: + if GenConstant.TREE_PARENT_CODE not in params_obj: raise ServiceException(message='树父编码字段不能为空') - elif GenConstant.TREE_NAME not in params_obj: + if GenConstant.TREE_NAME not in params_obj: raise ServiceException(message='树名称字段不能为空') - elif edit_gen_table.tpl_category == GenConstant.TPL_SUB: + if edit_gen_table.tpl_category == GenConstant.TPL_SUB: if not edit_gen_table.sub_table_name: raise ServiceException(message='关联子表的表名不能为空') - elif not edit_gen_table.sub_table_fk_name: + if not edit_gen_table.sub_table_fk_name: raise ServiceException(message='子表关联的外键名不能为空') @@ -483,7 +489,9 @@ class GenTableColumnService: """ @classmethod - async def get_gen_table_column_list_by_table_id_services(cls, query_db: AsyncSession, table_id: int): + async def get_gen_table_column_list_by_table_id_services( + cls, query_db: AsyncSession, table_id: int + ) -> list[GenTableColumnModel]: """ 获取业务表字段列表信息service diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index 13cc466..fa9de0e 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -1,5 +1,7 @@ {% set pkField = pkColumn.python_field %} {% set pk_field = pkColumn.python_field | camel_to_snake %} +{% set pkParentheseIndex = pkColumn.column_comment.find("(") %} +{% set pk_field_comment = pkColumn.column_comment[:pkParentheseIndex] if pkParentheseIndex != -1 else pkColumn.column_comment %} {% set need_import_datetime = namespace(has_datetime=False) %} {% for column in columns %} {% if column.python_field in ["createTime", "updatetime"] %} @@ -9,9 +11,12 @@ {% if need_import_datetime.has_datetime %} from datetime import datetime {% endif %} -from fastapi import APIRouter, Depends, Form, Request +from typing import Annotated + +from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession + from config.enums import BusinessType from config.get_db import get_db from module_admin.annotation.log_annotation import Log @@ -26,17 +31,17 @@ from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -{{ businessName }}Controller = APIRouter(prefix='/{{ moduleName }}/{{ businessName }}', dependencies=[Depends(LoginService.get_current_user)]) +{{ businessName }}_controller = APIRouter(prefix='/{{ moduleName }}/{{ businessName }}', dependencies=[Depends(LoginService.get_current_user)]) -@{{ businessName }}Controller.get( +@{{ businessName }}_controller.get( '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:list'))] ) async def get_{{ moduleName }}_{{ businessName }}_list( request: Request, - {% if table.crud or table.sub %}{{ businessName }}_page_query{% elif table.tree %}{{ businessName }}_query{% endif %}: {{ BusinessName }}PageQueryModel = Depends({{ BusinessName }}PageQueryModel.as_query), - query_db: AsyncSession = Depends(get_db), -): + {% if table.crud or table.sub %}{{ businessName }}_page_query{% elif table.tree %}{{ businessName }}_query{% endif %}: Annotated[{{ BusinessName }}PageQueryModel, Query()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: {% if table.crud or table.sub %} # 获取分页数据 {{ businessName }}_page_query_result = await {{ BusinessName }}Service.get_{{ businessName }}_list_services(query_db, {{ businessName }}_page_query, is_page=True) @@ -51,15 +56,15 @@ async def get_{{ moduleName }}_{{ businessName }}_list( {% endif %} -@{{ businessName }}Controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:add'))]) +@{{ businessName }}_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:add'))]) @ValidateFields(validate_model='add_{{ businessName }}') @Log(title='{{ functionName }}', business_type=BusinessType.INSERT) async def add_{{ moduleName }}_{{ businessName }}( request: Request, add_{{ businessName }}: {{ BusinessName }}Model, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: {% for column in columns %} {% if column.python_field == "createBy" %} add_{{ businessName }}.create_by = current_user.user.user_name @@ -77,15 +82,15 @@ async def add_{{ moduleName }}_{{ businessName }}( return ResponseUtil.success(msg=add_{{ businessName }}_result.message) -@{{ businessName }}Controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:edit'))]) +@{{ businessName }}_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:edit'))]) @ValidateFields(validate_model='edit_{{ businessName }}') @Log(title='{{ functionName }}', business_type=BusinessType.UPDATE) async def edit_{{ moduleName }}_{{ businessName }}( request: Request, edit_{{ businessName }}: {{ BusinessName }}Model, - query_db: AsyncSession = Depends(get_db), - current_user: CurrentUserModel = Depends(LoginService.get_current_user), -): + query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], +) -> Response: {% for column in columns %} {% if column.python_field == "updateBy" %} edit_{{ businessName }}.update_by = current_user.user.user_name @@ -99,9 +104,13 @@ async def edit_{{ moduleName }}_{{ businessName }}( return ResponseUtil.success(msg=edit_{{ businessName }}_result.message) -@{{ businessName }}Controller.delete('/{% raw %}{{% endraw %}{{ pk_field }}s{% raw %}}{% endraw %}', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:remove'))]) +@{{ businessName }}_controller.delete('/{% raw %}{{% endraw %}{{ pk_field }}s{% raw %}}{% endraw %}', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:remove'))]) @Log(title='{{ functionName }}', business_type=BusinessType.DELETE) -async def delete_{{ moduleName }}_{{ businessName }}(request: Request, {{ pk_field }}s: str, query_db: AsyncSession = Depends(get_db)): +async def delete_{{ moduleName }}_{{ businessName }}( + request: Request, + {{ pk_field }}s: Annotated[str, Path(description='需要删除的{{ pk_field_comment }}')], + Annotated[AsyncSession, Depends(get_db)], +) -> Response: delete_{{ businessName }} = Delete{{ BusinessName }}Model({{ pkField }}s={{ pk_field }}s) delete_{{ businessName }}_result = await {{ BusinessName }}Service.delete_{{ businessName }}_services(query_db, delete_{{ businessName }}) logger.info(delete_{{ businessName }}_result.message) @@ -109,23 +118,27 @@ async def delete_{{ moduleName }}_{{ businessName }}(request: Request, {{ pk_fie return ResponseUtil.success(msg=delete_{{ businessName }}_result.message) -@{{ businessName }}Controller.get( +@{{ businessName }}_controller.get( '/{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}', response_model={{ BusinessName }}Model, dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:query'))] ) -async def query_detail_{{ moduleName }}_{{ businessName }}(request: Request, {{ pk_field }}: int, query_db: AsyncSession = Depends(get_db)): +async def query_detail_{{ moduleName }}_{{ businessName }}( + request: Request, + {{ pk_field }}: Annotated[{{ pkColumn.python_type }}, Path(description='{{ pk_field_comment }}')], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: {{ businessName }}_detail_result = await {{ BusinessName }}Service.{{ businessName }}_detail_services(query_db, {{ pk_field }}) logger.info(f'获取{{ pk_field }}为{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}的信息成功') return ResponseUtil.success(data={{ businessName }}_detail_result) -@{{ businessName }}Controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:export'))]) +@{{ businessName }}_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:export'))]) @Log(title='{{ functionName }}', business_type=BusinessType.EXPORT) async def export_{{ moduleName }}_{{ businessName }}_list( request: Request, - {{ businessName }}_page_query: {{ BusinessName }}PageQueryModel = Form(), - query_db: AsyncSession = Depends(get_db), -): + {{ businessName }}_page_query: Annotated[{{ BusinessName }}PageQueryModel, Form()], + query_db: Annotated[AsyncSession, Depends(get_db)], +) -> Response: # 获取全量数据 {{ businessName }}_query_result = await {{ BusinessName }}Service.get_{{ businessName }}_list_services(query_db, {{ businessName }}_page_query, is_page=False) {{ businessName }}_export_result = await {{ BusinessName }}Service.export_{{ businessName }}_list_services({% if dicts %}request, {% endif %}{{ businessName }}_query_result) diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 index 3b186c5..477ee84 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 @@ -7,11 +7,14 @@ from datetime import datetime, time {% endif %} {% endfor %} +from typing import Any, Union + from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession {% if table.sub %} from sqlalchemy.orm import selectinload {% endif %} + {% if table.sub %} from {{ packageName }}.entity.do.{{ businessName }}_do import {{ ClassName }}, {{ subClassName }} from {{ packageName }}.entity.vo.{{ businessName }}_vo import {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel, {{ subTable.business_name | capitalize }}Model @@ -19,7 +22,7 @@ from {{ packageName }}.entity.vo.{{ businessName }}_vo import {{ BusinessName }} from {{ packageName }}.entity.do.{{ businessName }}_do import {{ ClassName }} from {{ packageName }}.entity.vo.{{ businessName }}_vo import {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel {% endif %} -from utils.page_util import PageUtil +from utils.page_util import PageResponseModel, PageUtil class {{ BusinessName }}Dao: @@ -28,7 +31,7 @@ class {{ BusinessName }}Dao: """ @classmethod - async def get_{{ businessName }}_detail_by_id(cls, db: AsyncSession, {{ pk_field }}: int): + async def get_{{ businessName }}_detail_by_id(cls, db: AsyncSession, {{ pk_field }}: int) -> Union[{{ ClassName }}, None]: """ 根据{{ pk_field_comment }}获取{{ functionName }}详细信息 @@ -57,7 +60,7 @@ class {{ BusinessName }}Dao: return {{ businessName }}_info @classmethod - async def get_{{ businessName }}_detail_by_info(cls, db: AsyncSession, {{ businessName }}: {{ BusinessName }}Model): + async def get_{{ businessName }}_detail_by_info(cls, db: AsyncSession, {{ businessName }}: {{ BusinessName }}Model) -> Union[{{ ClassName }}, None]: """ 根据{{ functionName }}参数获取{{ functionName }}信息 @@ -84,7 +87,9 @@ class {{ BusinessName }}Dao: return {{ businessName }}_info @classmethod - async def get_{{ businessName }}_list(cls, db: AsyncSession, query_object: {{ BusinessName }}PageQueryModel, is_page: bool = False): + async def get_{{ businessName }}_list( + cls, db: AsyncSession, query_object: {{ BusinessName }}PageQueryModel, is_page: bool = False + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 根据查询参数获取{{ functionName }}列表信息 @@ -132,12 +137,14 @@ class {{ BusinessName }}Dao: .order_by({{ ClassName }}.{{ pk_field }}) .distinct() ) - {{ businessName }}_list = await PageUtil.paginate(db, query, query_object.page_num, query_object.page_size, is_page) + {{ businessName }}_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + db, query, query_object.page_num, query_object.page_size, is_page + ) return {{ businessName }}_list @classmethod - async def add_{{ businessName }}_dao(cls, db: AsyncSession, {{ businessName }}: {{ BusinessName }}Model): + async def add_{{ businessName }}_dao(cls, db: AsyncSession, {{ businessName }}: {{ BusinessName }}Model) -> {{ ClassName }}: """ 新增{{ functionName }}数据库操作 @@ -152,7 +159,7 @@ class {{ BusinessName }}Dao: return db_{{ businessName }} @classmethod - async def edit_{{ businessName }}_dao(cls, db: AsyncSession, {{ businessName }}: dict): + async def edit_{{ businessName }}_dao(cls, db: AsyncSession, {{ businessName }}: dict) -> None: """ 编辑{{ functionName }}数据库操作 @@ -163,7 +170,7 @@ class {{ BusinessName }}Dao: await db.execute(update({{ ClassName }}), [{{ businessName }}]) @classmethod - async def delete_{{ businessName }}_dao(cls, db: AsyncSession, {{ businessName }}: {{ BusinessName }}Model): + async def delete_{{ businessName }}_dao(cls, db: AsyncSession, {{ businessName }}: {{ BusinessName }}Model) -> None: """ 删除{{ functionName }}数据库操作 @@ -175,7 +182,7 @@ class {{ BusinessName }}Dao: {% if table.sub %} @classmethod - async def add_{{ subTable.business_name }}_dao(cls, db: AsyncSession, {{ subTable.business_name }}: {{ subTable.business_name | capitalize }}Model): + async def add_{{ subTable.business_name }}_dao(cls, db: AsyncSession, {{ subTable.business_name }}: {{ subTable.business_name | capitalize }}Model) -> {{ subClassName }}: """ 新增{{ subTable.function_name }}数据库操作 @@ -190,7 +197,7 @@ class {{ BusinessName }}Dao: return db_{{ subTable.business_name }} @classmethod - async def edit_{{ subTable.business_name }}_dao(cls, db: AsyncSession, {{ subTable.business_name }}: dict): + async def edit_{{ subTable.business_name }}_dao(cls, db: AsyncSession, {{ subTable.business_name }}: dict) -> None: """ 编辑{{ subTable.function_name }}数据库操作 @@ -201,7 +208,7 @@ class {{ BusinessName }}Dao: await db.execute(update({{ subClassName }}), [{{ subTable.business_name }}]) @classmethod - async def delete_{{ subTable.business_name }}_dao(cls, db: AsyncSession, {{ subTable.business_name }}: {{ subTable.business_name | capitalize }}Model): + async def delete_{{ subTable.business_name }}_dao(cls, db: AsyncSession, {{ subTable.business_name }}: {{ subTable.business_name | capitalize }}Model) -> None: """ 删除{{ subTable.function_name }}数据库操作 diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/do.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/do.py.jinja2 index c7ea757..76137e3 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/do.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/do.py.jinja2 @@ -4,6 +4,7 @@ {% if table.sub %} from sqlalchemy.orm import relationship {% endif %} + from config.database import Base diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 index 5726c5d..a75563e 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 @@ -2,21 +2,24 @@ {% set pk_field = pkColumn.python_field | camel_to_snake %} {% set pkParentheseIndex = pkColumn.column_comment.find("(") %} {% set pk_field_comment = pkColumn.column_comment[:pkParentheseIndex] if pkParentheseIndex != -1 else pkColumn.column_comment %} +from typing import Any, Union + {% if dicts %} from fastapi import Request {% endif %} from sqlalchemy.ext.asyncio import AsyncSession -from typing import List + from config.constant import CommonConstant from exceptions.exception import ServiceException +from {{ packageName }}.dao.{{ businessName }}_dao import {{ BusinessName }}Dao from module_admin.entity.vo.common_vo import CrudResponseModel +from {{ packageName }}.entity.vo.{{ businessName }}_vo import Delete{{ BusinessName }}Model, {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel {% if dicts %} from module_admin.service.dict_service import DictDataService {% endif %} -from {{ packageName }}.dao.{{ businessName }}_dao import {{ BusinessName }}Dao -from {{ packageName }}.entity.vo.{{ businessName }}_vo import Delete{{ BusinessName }}Model, {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil +from utils.page_util import PageResponseModel class {{ BusinessName }}Service: @@ -27,7 +30,7 @@ class {{ BusinessName }}Service: @classmethod async def get_{{ businessName }}_list_services( cls, query_db: AsyncSession, query_object: {{ BusinessName }}PageQueryModel, is_page: bool = False - ): + ) -> Union[PageResponseModel, list[dict[str, Any]]]: """ 获取{{ functionName }}列表信息service @@ -45,7 +48,7 @@ class {{ BusinessName }}Service: {% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %} {% if column.unique %} @classmethod - async def check_{{ column.python_field | camel_to_snake }}_unique_services(cls, query_db: AsyncSession, page_object: {{ BusinessName }}Model): + async def check_{{ column.python_field | camel_to_snake }}_unique_services(cls, query_db: AsyncSession, page_object: {{ BusinessName }}Model) -> bool: """ 检查{{ comment }}是否唯一service @@ -63,7 +66,7 @@ class {{ BusinessName }}Service: {% endfor %} @classmethod - async def add_{{ businessName }}_services(cls, query_db: AsyncSession, page_object: {{ BusinessName }}Model): + async def add_{{ businessName }}_services(cls, query_db: AsyncSession, page_object: {{ BusinessName }}Model) -> CrudResponseModel: """ 新增{{ functionName }}信息service @@ -95,7 +98,7 @@ class {{ BusinessName }}Service: raise e @classmethod - async def edit_{{ businessName }}_services(cls, query_db: AsyncSession, page_object: {{ BusinessName }}Model): + async def edit_{{ businessName }}_services(cls, query_db: AsyncSession, page_object: {{ BusinessName }}Model) -> CrudResponseModel: """ 编辑{{ functionName }}信息service @@ -131,7 +134,7 @@ class {{ BusinessName }}Service: raise ServiceException(message='{{ functionName }}不存在') @classmethod - async def delete_{{ businessName }}_services(cls, query_db: AsyncSession, page_object: Delete{{ BusinessName }}Model): + async def delete_{{ businessName }}_services(cls, query_db: AsyncSession, page_object: Delete{{ BusinessName }}Model) -> CrudResponseModel: """ 删除{{ functionName }}信息service @@ -158,7 +161,7 @@ class {{ BusinessName }}Service: raise ServiceException(message='传入{{ pk_field_comment }}为空') @classmethod - async def {{ businessName }}_detail_services(cls, query_db: AsyncSession, {{ pk_field }}: int): + async def {{ businessName }}_detail_services(cls, query_db: AsyncSession, {{ pk_field }}: int) -> {{ BusinessName }}Model: """ 获取{{ functionName }}详细信息service @@ -167,15 +170,12 @@ class {{ BusinessName }}Service: :return: {{ pk_field_comment }}对应的信息 """ {{ businessName }} = await {{ BusinessName }}Dao.get_{{ businessName }}_detail_by_id(query_db, {{ pk_field }}={{ pk_field }}) - if {{ businessName }}: - result = {{ BusinessName }}Model(**CamelCaseUtil.transform_result({{ businessName }})) - else: - result = {{ BusinessName }}Model(**dict()) + result = {{ BusinessName }}Model(**CamelCaseUtil.transform_result({{ businessName }})) if {{ businessName }} else {{ BusinessName }}Model() return result @staticmethod - async def export_{{ businessName }}_list_services({% if dicts %}request: Request, {% endif %}{{ businessName }}_list: List): + async def export_{{ businessName }}_list_services({% if dicts %}request: Request, {% endif %}{{ businessName }}_list: list) -> bytes: """ 导出{{ functionName }}信息service @@ -195,13 +195,13 @@ class {{ BusinessName }}Service: {{ dict_type[1:-1] }}_list = await DictDataService.query_dict_data_list_from_cache_services( request.app.state.redis, dict_type={{ dict_type }} ) - {{ dict_type[1:-1] }}_option = [dict(label=item.get('dictLabel'), value=item.get('dictValue')) for item in {{ dict_type[1:-1] }}_list] + {{ dict_type[1:-1] }}_option = [{'label': item.get('dictLabel'), 'value': item.get('dictValue')} for item in {{ dict_type[1:-1] }}_list] {{ dict_type[1:-1] }}_option_dict = {item.get('value'): item for item in {{ dict_type[1:-1] }}_option} {% endfor %} for item in {{ businessName }}_list: {% for column in columns %} {% if column.dict_type %} - if str(item.get('{{ column.python_field }}')) in {{ column.dict_type }}_option_dict.keys(): + if str(item.get('{{ column.python_field }}')) in {{ column.dict_type }}_option_dict: item['{{ column.python_field }}'] = {{ column.dict_type }}_option_dict.get(str(item.get('{{ column.python_field }}'))).get('label') {% endif %} {% endfor %} diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/vo.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/vo.py.jinja2 index 47abbf5..f525d54 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/vo.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/vo.py.jinja2 @@ -23,17 +23,17 @@ {% for vo_import in voImportList %} {{ vo_import }} {% endfor %} +{% if table.sub %} +from typing import List, Optional +{% else %} +from typing import Optional, Union +{% endif %} + from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel {% if vo_field_required.has_required or sub_vo_field_required.has_required %} from pydantic_validation_decorator import NotBlank {% endif %} -{% if table.sub %} -from typing import List, Optional -{% else %} -from typing import Optional -{% endif %} -from module_admin.annotation.pydantic_annotation import as_query {% if table.sub %} @@ -53,14 +53,14 @@ class {{ BusinessName }}BaseModel(BaseModel): {% set parentheseIndex = column.column_comment.find("(") %} {% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %} @NotBlank(field_name='{{ column.column_name }}', message='{{ comment }}不能为空') - def get_{{ column.column_name }}(self): + def get_{{ column.column_name }}(self) -> Union[{{ column.python_type }}, None]: return self.{{ column.column_name }} {% if not loop.last %}{{ "\n" }}{% endif %} {% endif %} {% endfor %} {% if vo_field_required.has_required %} - def validate_fields(self): + def validate_fields(self) -> None: {% for column in columns %} {% if column.required %} self.get_{{ column.column_name }}() @@ -91,14 +91,14 @@ class {{ BusinessName }}Model({% if table.sub %}{{ BusinessName }}BaseModel{% el {% set parentheseIndex = column.column_comment.find("(") %} {% set comment = column.column_comment[:parentheseIndex] if parentheseIndex != -1 else column.column_comment %} @NotBlank(field_name='{{ column.column_name }}', message='{{ comment }}不能为空') - def get_{{ column.column_name }}(self): + def get_{{ column.column_name }}(self) -> Union[{{ column.python_type }}, None]: return self.{{ column.column_name }} {% if not loop.last %}{{ "\n" }}{% endif %} {% endif %} {% endfor %} {% if vo_field_required.has_required %} - def validate_fields(self): + def validate_fields(self) -> None: {% for column in columns %} {% if column.required %} self.get_{{ column.column_name }}() @@ -125,14 +125,14 @@ class {{ subTable.business_name | capitalize }}Model(BaseModel): {% set parentheseIndex = sub_column.column_comment.find("(") %} {% set comment = sub_column.column_comment[:parentheseIndex] if parentheseIndex != -1 else sub_column.column_comment %} @NotBlank(field_name='{{ sub_column.column_name }}', message='{{ comment }}不能为空') - def get_{{ sub_column.column_name }}(self): + def get_{{ sub_column.column_name }}(self) -> Union[{{ column.python_type }}, None]: return self.{{ sub_column.column_name }} {% if not loop.last %}{{ "\n" }}{% endif %} {% endif %} {% endfor %} {% if sub_vo_field_required.has_required %} - def validate_fields(self): + def validate_fields(self) -> None: {% for sub_column in subTable.columns %} {% if sub_column.required %} self.get_{{ sub_column.column_name }}() @@ -158,7 +158,6 @@ class {{ BusinessName }}QueryModel({% if table.sub %}{{ BusinessName }}BaseModel {% endif %} -@as_query class {{ BusinessName }}PageQueryModel({{ BusinessName }}QueryModel): """ {{ functionName }}分页查询模型 diff --git a/ruoyi-fastapi-backend/module_task/scheduler_test.py b/ruoyi-fastapi-backend/module_task/scheduler_test.py index b282732..7862c6d 100644 --- a/ruoyi-fastapi-backend/module_task/scheduler_test.py +++ b/ruoyi-fastapi-backend/module_task/scheduler_test.py @@ -1,7 +1,7 @@ from datetime import datetime -def job(*args, **kwargs): +def job(*args, **kwargs) -> None: """ 定时任务执行同步函数示例 """ @@ -10,7 +10,7 @@ def job(*args, **kwargs): print(f'{datetime.now()}同步函数执行了') -async def async_job(*args, **kwargs): +async def async_job(*args, **kwargs) -> None: """ 定时任务执行异步函数示例 """ diff --git a/ruoyi-fastapi-backend/requirements-pg.txt b/ruoyi-fastapi-backend/requirements-pg.txt index 9dbf1fd..a012eac 100644 --- a/ruoyi-fastapi-backend/requirements-pg.txt +++ b/ruoyi-fastapi-backend/requirements-pg.txt @@ -1,10 +1,11 @@ +aiofiles==25.1.0 alembic==1.16.4 APScheduler==3.11.0 async-lru==2.0.5 asyncpg==0.30.0 bcrypt==5.0.0 DateTime==5.5 -fastapi[all]==0.116.1 +fastapi[all]==0.123.9 loguru==0.7.3 openpyxl==3.1.5 pandas==2.3.2 @@ -14,6 +15,7 @@ pydantic-validation-decorator==0.1.4 PyJWT[crypto]==2.10.1 psycopg2==2.9.10 redis==6.4.0 +ruff==0.14.6 SQLAlchemy[asyncio]==2.0.43 sqlglot[rs]==27.8.0 user-agents==2.2.0 diff --git a/ruoyi-fastapi-backend/requirements.txt b/ruoyi-fastapi-backend/requirements.txt index af66bc7..5ae4b97 100644 --- a/ruoyi-fastapi-backend/requirements.txt +++ b/ruoyi-fastapi-backend/requirements.txt @@ -1,10 +1,11 @@ +aiofiles==25.1.0 alembic==1.16.4 APScheduler==3.11.0 async-lru==2.0.5 asyncmy==0.2.10 bcrypt==5.0.0 DateTime==5.5 -fastapi[all]==0.116.1 +fastapi[all]==0.123.9 loguru==0.7.3 openpyxl==3.1.5 pandas==2.3.2 @@ -14,6 +15,7 @@ pydantic-validation-decorator==0.1.4 PyJWT[crypto]==2.10.1 PyMySQL==1.1.1 redis==6.4.0 +ruff==0.14.6 SQLAlchemy[asyncio]==2.0.43 sqlglot[rs]==27.8.0 user-agents==2.2.0 diff --git a/ruoyi-fastapi-backend/ruff.toml b/ruoyi-fastapi-backend/ruff.toml index ea95368..61be1f7 100644 --- a/ruoyi-fastapi-backend/ruff.toml +++ b/ruoyi-fastapi-backend/ruff.toml @@ -1,4 +1,68 @@ line-length = 120 +show-fixes = true +target-version = "py39" +unsafe-fixes = true + +[lint] +select = [ + "FAST", # fastapi + "ANN", # flake8-annotations + "ASYNC", # flake8-async + "B", # flake8-bugbear + "A", # flake8-builtins + "COM", # flake8-commas + "C4", # flake8-comprehensions + "ISC", # flake8-implicit-str-concat + "ICN", # flake8-import-conventions + "PIE", # flake8-pie + "RSE", # flake8-raise + "RET", # flake8-return + "SIM", # flake8-simplify + "TC", # flake8-type-checking + "FLY", # flynt + "I", # isort + "N", # pep8-naming + "PERF", # perflint + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "PGH", # pygrep-hooks + "PL", # pylint + "UP", # pyupgrade + "RUF", # Ruff-specific rules +] +ignore = [ + "ANN002", # missing type annotation for *{name} + "ANN003", # missing type annotation for **{name} + "ANN401", # dynamically typed expressions (typing.Any) are disallowed in {name} + "B008", # do not perform function calls in argument defaults + "COM812", # trailing comma missing + "RET504", # unnecessary assignment to {name} before return statement + "SIM105", # use contextlib.suppress({exception}) instead of try-except-pass + "C901", # too complex + "N818", # exception name {name} should be named with an Error suffix + "E501", # line too long + "W191", # indentation contains tabs + "RUF001", # string contains ambiguous + "RUF002", # docstring contains ambiguous + "RUF003", # comment contains ambiguous + "RUF012", # mutable class attributes should be annotated with typing.ClassVar +] + +[lint.flake8-type-checking] +runtime-evaluated-base-classes = ["pydantic.BaseModel", "sqlalchemy.orm.DeclarativeBase"] + +[lint.isort] +known-third-party = ["alembic"] + +[lint.pylint] +max-args = 10 +max-returns = 10 + +[lint.pyupgrade] +# Preserve types, even if a file imports `from __future__ import annotations`. +keep-runtime-typing = true [format] +docstring-code-format = true quote-style = "single" \ No newline at end of file diff --git a/ruoyi-fastapi-backend/server.py b/ruoyi-fastapi-backend/server.py index 7a46e77..d401110 100644 --- a/ruoyi-fastapi-backend/server.py +++ b/ruoyi-fastapi-backend/server.py @@ -1,28 +1,31 @@ +from collections.abc import AsyncGenerator from contextlib import asynccontextmanager + from fastapi import FastAPI + from config.env import AppConfig from config.get_db import init_create_table from config.get_redis import RedisUtil from config.get_scheduler import SchedulerUtil from exceptions.handle import handle_exception from middlewares.handle import handle_middleware -from module_admin.controller.cache_controller import cacheController -from module_admin.controller.captcha_controller import captchaController -from module_admin.controller.common_controller import commonController -from module_admin.controller.config_controller import configController -from module_admin.controller.dept_controller import deptController -from module_admin.controller.dict_controller import dictController -from module_admin.controller.log_controller import logController -from module_admin.controller.login_controller import loginController -from module_admin.controller.job_controller import jobController -from module_admin.controller.menu_controller import menuController -from module_admin.controller.notice_controller import noticeController -from module_admin.controller.online_controller import onlineController -from module_admin.controller.post_controler import postController -from module_admin.controller.role_controller import roleController -from module_admin.controller.server_controller import serverController -from module_admin.controller.user_controller import userController -from module_generator.controller.gen_controller import genController +from module_admin.controller.cache_controller import cache_controller +from module_admin.controller.captcha_controller import captcha_controller +from module_admin.controller.common_controller import common_controller +from module_admin.controller.config_controller import config_controller +from module_admin.controller.dept_controller import dept_controller +from module_admin.controller.dict_controller import dict_controller +from module_admin.controller.job_controller import job_controller +from module_admin.controller.log_controller import log_controller +from module_admin.controller.login_controller import login_controller +from module_admin.controller.menu_controller import menu_controller +from module_admin.controller.notice_controller import notice_controller +from module_admin.controller.online_controller import online_controller +from module_admin.controller.post_controller import post_controller +from module_admin.controller.role_controller import role_controller +from module_admin.controller.server_controller import server_controller +from module_admin.controller.user_controller import user_controller +from module_generator.controller.gen_controller import gen_controller from sub_applications.handle import handle_sub_applications from utils.common_util import worship from utils.log_util import logger @@ -30,7 +33,7 @@ from utils.log_util import logger # 生命周期事件 @asynccontextmanager -async def lifespan(app: FastAPI): +async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: logger.info(f'⏰️ {AppConfig.app_name}开始启动') worship() await init_create_table() @@ -62,23 +65,23 @@ handle_exception(app) # 加载路由列表 controller_list = [ - {'router': loginController, 'tags': ['登录模块']}, - {'router': captchaController, 'tags': ['验证码模块']}, - {'router': userController, 'tags': ['系统管理-用户管理']}, - {'router': roleController, 'tags': ['系统管理-角色管理']}, - {'router': menuController, 'tags': ['系统管理-菜单管理']}, - {'router': deptController, 'tags': ['系统管理-部门管理']}, - {'router': postController, 'tags': ['系统管理-岗位管理']}, - {'router': dictController, 'tags': ['系统管理-字典管理']}, - {'router': configController, 'tags': ['系统管理-参数管理']}, - {'router': noticeController, 'tags': ['系统管理-通知公告管理']}, - {'router': logController, 'tags': ['系统管理-日志管理']}, - {'router': onlineController, 'tags': ['系统监控-在线用户']}, - {'router': jobController, 'tags': ['系统监控-定时任务']}, - {'router': serverController, 'tags': ['系统监控-菜单管理']}, - {'router': cacheController, 'tags': ['系统监控-缓存监控']}, - {'router': commonController, 'tags': ['通用模块']}, - {'router': genController, 'tags': ['代码生成']}, + {'router': login_controller, 'tags': ['登录模块']}, + {'router': captcha_controller, 'tags': ['验证码模块']}, + {'router': user_controller, 'tags': ['系统管理-用户管理']}, + {'router': role_controller, 'tags': ['系统管理-角色管理']}, + {'router': menu_controller, 'tags': ['系统管理-菜单管理']}, + {'router': dept_controller, 'tags': ['系统管理-部门管理']}, + {'router': post_controller, 'tags': ['系统管理-岗位管理']}, + {'router': dict_controller, 'tags': ['系统管理-字典管理']}, + {'router': config_controller, 'tags': ['系统管理-参数管理']}, + {'router': notice_controller, 'tags': ['系统管理-通知公告管理']}, + {'router': log_controller, 'tags': ['系统管理-日志管理']}, + {'router': online_controller, 'tags': ['系统监控-在线用户']}, + {'router': job_controller, 'tags': ['系统监控-定时任务']}, + {'router': server_controller, 'tags': ['系统监控-服务监控']}, + {'router': cache_controller, 'tags': ['系统监控-缓存监控']}, + {'router': common_controller, 'tags': ['通用模块']}, + {'router': gen_controller, 'tags': ['代码生成']}, ] for controller in controller_list: diff --git a/ruoyi-fastapi-backend/sub_applications/handle.py b/ruoyi-fastapi-backend/sub_applications/handle.py index df2a5f4..325193e 100644 --- a/ruoyi-fastapi-backend/sub_applications/handle.py +++ b/ruoyi-fastapi-backend/sub_applications/handle.py @@ -1,8 +1,9 @@ from fastapi import FastAPI + from sub_applications.staticfiles import mount_staticfiles -def handle_sub_applications(app: FastAPI): +def handle_sub_applications(app: FastAPI) -> None: """ 全局处理子应用挂载 """ diff --git a/ruoyi-fastapi-backend/sub_applications/staticfiles.py b/ruoyi-fastapi-backend/sub_applications/staticfiles.py index c481d72..5e5d4e5 100644 --- a/ruoyi-fastapi-backend/sub_applications/staticfiles.py +++ b/ruoyi-fastapi-backend/sub_applications/staticfiles.py @@ -1,9 +1,10 @@ from fastapi import FastAPI from fastapi.staticfiles import StaticFiles + from config.env import UploadConfig -def mount_staticfiles(app: FastAPI): +def mount_staticfiles(app: FastAPI) -> None: """ 挂载静态文件 """ diff --git a/ruoyi-fastapi-backend/utils/common_util.py b/ruoyi-fastapi-backend/utils/common_util.py index 0ccb546..43ab2d2 100644 --- a/ruoyi-fastapi-backend/utils/common_util.py +++ b/ruoyi-fastapi-backend/utils/common_util.py @@ -1,7 +1,10 @@ import io import os -import pandas as pd import re +from collections.abc import Generator, Sequence +from typing import Any, Literal, Union, overload + +import pandas as pd from openpyxl import Workbook from openpyxl.styles import Alignment, PatternFill from openpyxl.utils import get_column_letter @@ -9,13 +12,13 @@ from openpyxl.worksheet.datavalidation import DataValidation from sqlalchemy.engine.row import Row from sqlalchemy.orm.collections import InstrumentedList from sqlalchemy.sql.expression import TextClause, null -from typing import Any, Dict, List, Literal, Union + from config.database import Base from config.env import CachePathConfig -def worship(): - print(""" +def worship() -> None: + print(r""" //////////////////////////////////////////////////////////////////// // _ooOoo_ // // o8888888o // @@ -36,7 +39,7 @@ def worship(): // ========`-.____`-.___\_____/___.-`____.-'======== // // `=---=' // // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // -// 佛祖保佑 永不宕机 永无BUG // +// 佛祖保佑 永不宕机 永无BUG // //////////////////////////////////////////////////////////////////// """) @@ -48,8 +51,8 @@ class SqlalchemyUtil: @classmethod def base_to_dict( - cls, obj: Union[Base, Dict], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' - ): + cls, obj: Union[Base, dict], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> dict: """ 将sqlalchemy模型对象转换为字典 @@ -67,15 +70,63 @@ class SqlalchemyUtil: base_dict = obj.copy() if transform_case == 'snake_to_camel': return {CamelCaseUtil.snake_to_camel(k): v for k, v in base_dict.items()} - elif transform_case == 'camel_to_snake': + if transform_case == 'camel_to_snake': return {SnakeCaseUtil.camel_to_snake(k): v for k, v in base_dict.items()} return base_dict @classmethod + @overload + def serialize_result( + cls, result: Base, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> dict[str, Any]: ... + + @classmethod + @overload + def serialize_result( + cls, result: dict, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> dict[Any, Any]: ... + + @classmethod + @overload + def serialize_result( + cls, result: Row, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> Union[dict[str, Any], list[dict[Any, Any]]]: ... + + @classmethod + @overload + def serialize_result( + cls, result: Sequence[Base], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> list[dict[str, Any]]: ... + + @classmethod + @overload + def serialize_result( + cls, result: Sequence[dict], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> list[dict[Any, Any]]: ... + + @classmethod + @overload + def serialize_result( + cls, result: Sequence[Row], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> list[Union[dict[str, Any], list[dict[Any, Any]]]]: ... + + @classmethod + @overload + def serialize_result( + cls, result: Sequence[Any], transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> list[Any]: ... + + @classmethod + @overload def serialize_result( cls, result: Any, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' - ): + ) -> Any: ... + + @classmethod + def serialize_result( + cls, result: Any, transform_case: Literal['no_case', 'snake_to_camel', 'camel_to_snake'] = 'no_case' + ) -> Any: """ 将sqlalchemy查询结果序列化 @@ -85,20 +136,19 @@ class SqlalchemyUtil: """ if isinstance(result, (Base, dict)): return cls.base_to_dict(result, transform_case) - elif isinstance(result, list): + if isinstance(result, list): return [cls.serialize_result(row, transform_case) for row in result] - elif isinstance(result, Row): - if all([isinstance(row, Base) for row in result]): + if isinstance(result, Row): + if all(isinstance(row, Base) for row in result): return [cls.base_to_dict(row, transform_case) for row in result] - elif any([isinstance(row, Base) for row in result]): + if any(isinstance(row, Base) for row in result): return [cls.serialize_result(row, transform_case) for row in result] - else: - result_dict = result._asdict() - if transform_case == 'snake_to_camel': - return {CamelCaseUtil.snake_to_camel(k): v for k, v in result_dict.items()} - elif transform_case == 'camel_to_snake': - return {SnakeCaseUtil.camel_to_snake(k): v for k, v in result_dict.items()} - return result_dict + result_dict = result._asdict() + if transform_case == 'snake_to_camel': + return {CamelCaseUtil.snake_to_camel(k): v for k, v in result_dict.items()} + if transform_case == 'camel_to_snake': + return {SnakeCaseUtil.camel_to_snake(k): v for k, v in result_dict.items()} + return result_dict return result @classmethod @@ -121,7 +171,7 @@ class CamelCaseUtil: """ @classmethod - def snake_to_camel(cls, snake_str: str): + def snake_to_camel(cls, snake_str: str) -> str: """ 下划线形式字符串(snake_case)转换为小驼峰形式字符串(camelCase) @@ -134,7 +184,39 @@ class CamelCaseUtil: return words[0] + ''.join(word.capitalize() for word in words[1:]) @classmethod - def transform_result(cls, result: Any): + @overload + def transform_result(cls, result: Base) -> dict[str, Any]: ... + + @classmethod + @overload + def transform_result(cls, result: dict) -> dict[Any, Any]: ... + + @classmethod + @overload + def transform_result(cls, result: Row) -> Union[dict[str, Any], list[dict[Any, Any]]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[Base]) -> list[dict[str, Any]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[dict]) -> list[dict[Any, Any]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[Row]) -> list[Union[dict[str, Any], list[dict[Any, Any]]]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[Any]) -> list[Any]: ... + + @classmethod + @overload + def transform_result(cls, result: Any) -> Any: ... + + @classmethod + def transform_result(cls, result: Any) -> Any: """ 针对不同类型将下划线形式(snake_case)批量转换为小驼峰形式(camelCase)方法 @@ -150,7 +232,7 @@ class SnakeCaseUtil: """ @classmethod - def camel_to_snake(cls, camel_str: str): + def camel_to_snake(cls, camel_str: str) -> str: """ 小驼峰形式字符串(camelCase)转换为下划线形式字符串(snake_case) @@ -162,17 +244,49 @@ class SnakeCaseUtil: return re.sub('([a-z0-9])([A-Z])', r'\1_\2', words).lower() @classmethod - def transform_result(cls, result: Any): + @overload + def transform_result(cls, result: Base) -> dict[str, Any]: ... + + @classmethod + @overload + def transform_result(cls, result: dict) -> dict[Any, Any]: ... + + @classmethod + @overload + def transform_result(cls, result: Row) -> Union[dict[str, Any], list[dict[Any, Any]]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[Base]) -> list[dict[str, Any]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[dict]) -> list[dict[Any, Any]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[Row]) -> list[Union[dict[str, Any], list[dict[Any, Any]]]]: ... + + @classmethod + @overload + def transform_result(cls, result: Sequence[Any]) -> list[Any]: ... + + @classmethod + @overload + def transform_result(cls, result: Any) -> Any: ... + + @classmethod + def transform_result(cls, result: Any) -> Any: """ - 针对不同类型将下划线形式(snake_case)批量转换为小驼峰形式(camelCase)方法 + 针对不同类型将小驼峰形式(camelCase)批量转换为下划线形式(snake_case)方法 :param result: 输入数据 - :return: 小驼峰形式结果 + :return: 下划线形式结果 """ return SqlalchemyUtil.serialize_result(result=result, transform_case='camel_to_snake') -def bytes2human(n, format_str='%(value).1f%(symbol)s'): +def bytes2human(n: int, format_str: str = '%(value).1f%(symbol)s') -> str: """Used by various scripts. See: http://goo.gl/zeJZl @@ -189,14 +303,14 @@ def bytes2human(n, format_str='%(value).1f%(symbol)s'): if n >= prefix[symbol]: value = float(n) / prefix[symbol] return format_str % locals() - return format_str % dict(symbol=symbols[0], value=n) + return format_str % {'symbol': symbols[0], 'value': n} -def bytes2file_response(bytes_info): +def bytes2file_response(bytes_info: bytes) -> Generator[bytes]: yield bytes_info -def export_list2excel(list_data: List): +def export_list2excel(list_data: list) -> bytes: """ 工具方法:将需要导出的list数据转化为对应excel的二进制数据 @@ -211,7 +325,7 @@ def export_list2excel(list_data: List): return binary_data -def get_excel_template(header_list: List, selector_header_list: List, option_list: List[dict]): +def get_excel_template(header_list: list, selector_header_list: list, option_list: list[dict]) -> bytes: """ 工具方法:将需要导出的list数据转化为对应excel的二进制数据 @@ -272,7 +386,7 @@ def get_excel_template(header_list: List, selector_header_list: List, option_lis return excel_data -def get_filepath_from_url(url: str): +def get_filepath_from_url(url: str) -> str: """ 工具方法:根据请求参数获取文件路径 diff --git a/ruoyi-fastapi-backend/utils/cron_util.py b/ruoyi-fastapi-backend/utils/cron_util.py index 6232962..045f4ea 100644 --- a/ruoyi-fastapi-backend/utils/cron_util.py +++ b/ruoyi-fastapi-backend/utils/cron_util.py @@ -7,8 +7,13 @@ class CronUtil: Cron表达式工具类 """ + ONE_YEAR_LENGTH = 4 + MAX_YEAR = 2099 + CRON_EXPRESSION_LENGTH_MIN = 6 + CRON_EXPRESSION_LENGTH_MAX = 7 + @classmethod - def __valid_range(cls, search_str: str, start_range: int, end_range: int): + def __valid_range(cls, search_str: str, start_range: int, end_range: int) -> bool: match = re.match(r'^(\d+)-(\d+)$', search_str) if match: start, end = int(match.group(1)), int(match.group(2)) @@ -18,7 +23,7 @@ class CronUtil: @classmethod def __valid_sum( cls, search_str: str, start_range_a: int, start_range_b: int, end_range_a: int, end_range_b: int, sum_range: int - ): + ) -> bool: match = re.match(r'^(\d+)/(\d+)$', search_str) if match: start, end = int(match.group(1)), int(match.group(2)) @@ -30,94 +35,84 @@ class CronUtil: return False @classmethod - def validate_second_or_minute(cls, second_or_minute: str): + def validate_second_or_minute(cls, second_or_minute: str) -> bool: """ 校验秒或分钟值是否正确 :param second_or_minute: 秒或分钟值 :return: 校验结果 """ - if ( + return bool( second_or_minute == '*' or ('-' in second_or_minute and cls.__valid_range(second_or_minute, 0, 59)) or ('/' in second_or_minute and cls.__valid_sum(second_or_minute, 0, 58, 1, 59, 59)) or re.match(r'^(?:[0-5]?\d|59)(?:,[0-5]?\d|59)*$', second_or_minute) - ): - return True - return False + ) @classmethod - def validate_hour(cls, hour: str): + def validate_hour(cls, hour: str) -> bool: """ 校验小时值是否正确 :param hour: 小时值 :return: 校验结果 """ - if ( + return bool( hour == '*' or ('-' in hour and cls.__valid_range(hour, 0, 23)) or ('/' in hour and cls.__valid_sum(hour, 0, 22, 1, 23, 23)) or re.match(r'^(?:0|[1-9]|1\d|2[0-3])(?:,(?:0|[1-9]|1\d|2[0-3]))*$', hour) - ): - return True - return False + ) @classmethod - def validate_day(cls, day: str): + def validate_day(cls, day: str) -> bool: """ 校验日值是否正确 :param day: 日值 :return: 校验结果 """ - if ( + return bool( day in ['*', '?', 'L'] or ('-' in day and cls.__valid_range(day, 1, 31)) or ('/' in day and cls.__valid_sum(day, 1, 30, 1, 30, 31)) or ('W' in day and re.match(r'^(?:[1-9]|1\d|2\d|3[01])W$', day)) or re.match(r'^(?:0|[1-9]|1\d|2[0-9]|3[0-1])(?:,(?:0|[1-9]|1\d|2[0-9]|3[0-1]))*$', day) - ): - return True - return False + ) @classmethod - def validate_month(cls, month: str): + def validate_month(cls, month: str) -> bool: """ 校验月值是否正确 :param month: 月值 :return: 校验结果 """ - if ( + return bool( month == '*' or ('-' in month and cls.__valid_range(month, 1, 12)) or ('/' in month and cls.__valid_sum(month, 1, 11, 1, 11, 12)) or re.match(r'^(?:0|[1-9]|1[0-2])(?:,(?:0|[1-9]|1[0-2]))*$', month) - ): - return True - return False + ) @classmethod - def validate_week(cls, week: str): + def validate_week(cls, week: str) -> bool: """ 校验周值是否正确 :param week: 周值 :return: 校验结果 """ - if ( + return bool( week in ['*', '?'] or ('-' in week and cls.__valid_range(week, 1, 7)) or ('#' in week and re.match(r'^[1-7]#[1-4]$', week)) or ('L' in week and re.match(r'^[1-7]L$', week)) or re.match(r'^[1-7](?:(,[1-7]))*$', week) - ): - return True - return False + ) @classmethod - def validate_year(cls, year: str): + def validate_year(cls, year: str) -> bool: """ 校验年值是否正确 @@ -126,22 +121,22 @@ class CronUtil: """ current_year = int(datetime.now().year) future_years = [current_year + i for i in range(9)] - if ( + return bool( year == '*' or ('-' in year and cls.__valid_range(year, current_year, 2099)) or ('/' in year and cls.__valid_sum(year, current_year, 2098, 1, 2099 - current_year, 2099)) or ('#' in year and re.match(r'^[1-7]#[1-4]$', year)) or ('L' in year and re.match(r'^[1-7]L$', year)) or ( - (len(year) == 4 or ',' in year) - and all(int(item) in future_years and current_year <= int(item) <= 2099 for item in year.split(',')) + (len(year) == cls.ONE_YEAR_LENGTH or ',' in year) + and all( + int(item) in future_years and current_year <= int(item) <= cls.MAX_YEAR for item in year.split(',') + ) ) - ): - return True - return False + ) @classmethod - def validate_cron_expression(cls, cron_expression: str): + def validate_cron_expression(cls, cron_expression: str) -> bool: """ 校验Cron表达式是否正确 @@ -149,7 +144,7 @@ class CronUtil: :return: 校验结果 """ values = cron_expression.split() - if len(values) != 6 and len(values) != 7: + if len(values) != cls.CRON_EXPRESSION_LENGTH_MIN and len(values) != cls.CRON_EXPRESSION_LENGTH_MAX: return False second_validation = cls.validate_second_or_minute(values[0]) minute_validation = cls.validate_second_or_minute(values[1]) @@ -165,8 +160,7 @@ class CronUtil: and month_validation and week_validation ) - if len(values) == 6: + if len(values) == cls.CRON_EXPRESSION_LENGTH_MIN: return validation - if len(values) == 7: - year_validation = cls.validate_year(values[6]) - return validation and year_validation + year_validation = cls.validate_year(values[6]) + return validation and year_validation diff --git a/ruoyi-fastapi-backend/utils/excel_util.py b/ruoyi-fastapi-backend/utils/excel_util.py index 875a41d..07168d1 100644 --- a/ruoyi-fastapi-backend/utils/excel_util.py +++ b/ruoyi-fastapi-backend/utils/excel_util.py @@ -1,10 +1,10 @@ import io + import pandas as pd from openpyxl import Workbook from openpyxl.styles import Alignment, PatternFill from openpyxl.utils import get_column_letter from openpyxl.worksheet.datavalidation import DataValidation -from typing import Dict, List class ExcelUtil: @@ -13,7 +13,7 @@ class ExcelUtil: """ @classmethod - def __mapping_list(cls, list_data: List, mapping_dict: Dict): + def __mapping_list(cls, list_data: list, mapping_dict: dict) -> list[dict]: """ 工具方法:将list数据中的字段名映射为对应的中文字段名 @@ -26,7 +26,7 @@ class ExcelUtil: return mapping_data @classmethod - def export_list2excel(cls, list_data: List, mapping_dict: Dict): + def export_list2excel(cls, list_data: list, mapping_dict: dict) -> bytes: """ 工具方法:将需要导出的list数据转化为对应excel的二进制数据 @@ -43,7 +43,7 @@ class ExcelUtil: return binary_data @classmethod - def get_excel_template(cls, header_list: List, selector_header_list: List, option_list: List[Dict]): + def get_excel_template(cls, header_list: list, selector_header_list: list, option_list: list[dict]) -> bytes: """ 工具方法:将需要导出的list数据转化为对应excel的二进制数据 diff --git a/ruoyi-fastapi-backend/utils/gen_util.py b/ruoyi-fastapi-backend/utils/gen_util.py index 355e5d0..68d3419 100644 --- a/ruoyi-fastapi-backend/utils/gen_util.py +++ b/ruoyi-fastapi-backend/utils/gen_util.py @@ -1,6 +1,6 @@ import re from datetime import datetime -from typing import List + from config.constant import GenConstant from config.env import GenConfig from module_generator.entity.vo.gen_vo import GenTableColumnModel, GenTableModel @@ -10,6 +10,8 @@ from utils.string_util import StringUtil class GenUtils: """代码生成器工具类""" + TEXTAREA_COLUMN_LENGTH = 500 + @classmethod def init_table(cls, gen_table: GenTableModel, oper_name: str) -> None: """ @@ -58,7 +60,8 @@ class GenUtils: column_length = cls.get_column_length(column.column_type) html_type = ( GenConstant.HTML_TEXTAREA - if column_length >= 500 or cls.arrays_contains(GenConstant.COLUMNTYPE_TEXT, data_type) + if column_length >= cls.TEXTAREA_COLUMN_LENGTH + or cls.arrays_contains(GenConstant.COLUMNTYPE_TEXT, data_type) else GenConstant.HTML_INPUT ) column.html_type = html_type @@ -98,14 +101,14 @@ class GenUtils: # 内容字段设置富文本控件 elif column_name.lower().endswith('content'): column.html_type = GenConstant.HTML_EDITOR - + column.create_by = table.create_by column.create_time = datetime.now() column.update_by = table.update_by column.update_time = datetime.now() @classmethod - def arrays_contains(cls, arr: List[str], target_value: str) -> bool: + def arrays_contains(cls, arr: list[str], target_value: str) -> bool: """ 校验数组是否包含指定值 @@ -151,7 +154,7 @@ class GenUtils: return StringUtil.convert_to_camel_case(table_name) @classmethod - def replace_first(cls, replacement: str, search_list: List[str]) -> str: + def replace_first(cls, replacement: str, search_list: list[str]) -> str: """ 批量替换前缀 @@ -200,7 +203,7 @@ class GenUtils: return 0 @classmethod - def split_column_type(cls, column_type: str) -> List[str]: + def split_column_type(cls, column_type: str) -> list[str]: """ 拆分列类型 diff --git a/ruoyi-fastapi-backend/utils/import_util.py b/ruoyi-fastapi-backend/utils/import_util.py index 4bb2a63..c349e9c 100644 --- a/ruoyi-fastapi-backend/utils/import_util.py +++ b/ruoyi-fastapi-backend/utils/import_util.py @@ -1,11 +1,13 @@ import importlib import inspect import os -from pathlib import Path import sys from functools import lru_cache +from pathlib import Path +from typing import Any + from sqlalchemy import inspect as sa_inspect -from typing import Any, List + from config.database import Base @@ -49,7 +51,7 @@ class ImportUtil: @classmethod @lru_cache(maxsize=256) - def find_models(cls, base_class: Base) -> List[Base]: + def find_models(cls, base_class: Base) -> list[Base]: """ 查找并过滤有效的模型类,避免重复和无效定义 @@ -64,7 +66,7 @@ class ImportUtil: project_root = cls.find_project_root() sys.path.append(str(project_root)) - print(f"⏰️ 开始在项目根目录 {project_root} 中查找模型...") + print(f'⏰️ 开始在项目根目录 {project_root} 中查找模型...') # 排除目录扩展 exclude_dirs = { @@ -87,13 +89,13 @@ class ImportUtil: for file in files: if file.endswith('.py') and not file.startswith('__'): relative_path = Path(root).relative_to(project_root) - module_parts = list(relative_path.parts) + [file[:-3]] + module_parts = [*list(relative_path.parts), file[:-3]] module_name = '.'.join(module_parts) try: module = importlib.import_module(module_name) - for name, obj in inspect.getmembers(module, inspect.isclass): + for _name, obj in inspect.getmembers(module, inspect.isclass): # 验证模型有效性 if not cls.is_valid_model(obj, base_class): continue diff --git a/ruoyi-fastapi-backend/utils/log_util.py b/ruoyi-fastapi-backend/utils/log_util.py index f953f55..8996306 100644 --- a/ruoyi-fastapi-backend/utils/log_util.py +++ b/ruoyi-fastapi-backend/utils/log_util.py @@ -1,18 +1,20 @@ import os import sys import time + from loguru import logger as _logger -from typing import Dict +from loguru._logger import Logger + from middlewares.trace_middleware import TraceCtx class LoggerInitializer: - def __init__(self): + def __init__(self) -> None: self.log_path = os.path.join(os.getcwd(), 'logs') self.__ensure_log_directory_exists() self.log_path_error = os.path.join(self.log_path, f'{time.strftime("%Y-%m-%d")}_error.log') - def __ensure_log_directory_exists(self): + def __ensure_log_directory_exists(self) -> None: """ 确保日志目录存在,如果不存在则创建 """ @@ -20,14 +22,14 @@ class LoggerInitializer: os.mkdir(self.log_path) @staticmethod - def __filter(log: Dict): + def __filter(log: dict) -> dict: """ 自定义日志过滤器,添加trace_id """ log['trace_id'] = TraceCtx.get_id() return log - def init_log(self): + def init_log(self) -> Logger: """ 初始化日志配置 """ diff --git a/ruoyi-fastapi-backend/utils/message_util.py b/ruoyi-fastapi-backend/utils/message_util.py index 3d3eb51..b425d3b 100644 --- a/ruoyi-fastapi-backend/utils/message_util.py +++ b/ruoyi-fastapi-backend/utils/message_util.py @@ -1,5 +1,5 @@ from utils.log_util import logger -def message_service(sms_code: str): +def message_service(sms_code: str) -> None: logger.info(f'短信验证码为{sms_code}') diff --git a/ruoyi-fastapi-backend/utils/page_util.py b/ruoyi-fastapi-backend/utils/page_util.py index dfe8a31..29b7f38 100644 --- a/ruoyi-fastapi-backend/utils/page_util.py +++ b/ruoyi-fastapi-backend/utils/page_util.py @@ -1,9 +1,11 @@ import math +from typing import Any, Optional, Union + from pydantic import BaseModel, ConfigDict from pydantic.alias_generators import to_camel -from sqlalchemy import func, select, Select +from sqlalchemy import Row, Select, func, select from sqlalchemy.ext.asyncio import AsyncSession -from typing import Optional, List + from utils.common_util import CamelCaseUtil @@ -14,7 +16,7 @@ class PageResponseModel(BaseModel): model_config = ConfigDict(alias_generator=to_camel) - rows: List = [] + rows: list = [] page_num: Optional[int] = None page_size: Optional[int] = None total: int @@ -27,7 +29,7 @@ class PageUtil: """ @classmethod - def get_page_obj(cls, data_list: List, page_num: int, page_size: int): + def get_page_obj(cls, data_list: list, page_num: int, page_size: int) -> PageResponseModel: """ 输入数据列表data_list和分页信息,返回分页数据列表结果 @@ -42,7 +44,7 @@ class PageUtil: # 根据计算得到的起始索引和结束索引对数据列表进行切片 paginated_data = data_list[start:end] - has_next = True if math.ceil(len(data_list) / page_size) > page_num else False + has_next = math.ceil(len(data_list) / page_size) > page_num result = PageResponseModel( rows=paginated_data, pageNum=page_num, pageSize=page_size, total=len(data_list), hasNext=has_next @@ -51,7 +53,9 @@ class PageUtil: return result @classmethod - async def paginate(cls, db: AsyncSession, query: Select, page_num: int, page_size: int, is_page: bool = False): + async def paginate( + cls, db: AsyncSession, query: Select, page_num: int, page_size: int, is_page: bool = False + ) -> Union[PageResponseModel, list[Union[dict[str, Any], list[dict[Any, Any]]]]]: """ 输入查询语句和分页信息,返回分页数据列表结果 @@ -65,7 +69,7 @@ class PageUtil: if is_page: total = (await db.execute(select(func.count('*')).select_from(query.subquery()))).scalar() query_result = await db.execute(query.offset((page_num - 1) * page_size).limit(page_size)) - paginated_data = [] + paginated_data: list[Row] = [] for row in query_result: if row and len(row) == 1: paginated_data.append(row[0]) @@ -81,7 +85,7 @@ class PageUtil: ) else: query_result = await db.execute(query) - no_paginated_data = [] + no_paginated_data: list[Row] = [] for row in query_result: if row and len(row) == 1: no_paginated_data.append(row[0]) @@ -92,7 +96,7 @@ class PageUtil: return result -def get_page_obj(data_list: List, page_num: int, page_size: int): +def get_page_obj(data_list: list, page_num: int, page_size: int) -> PageResponseModel: """ 输入数据列表data_list和分页信息,返回分页数据列表结果 @@ -107,7 +111,7 @@ def get_page_obj(data_list: List, page_num: int, page_size: int): # 根据计算得到的起始索引和结束索引对数据列表进行切片 paginated_data = data_list[start:end] - has_next = True if math.ceil(len(data_list) / page_size) > page_num else False + has_next = math.ceil(len(data_list) / page_size) > page_num result = PageResponseModel( rows=paginated_data, pageNum=page_num, pageSize=page_size, total=len(data_list), hasNext=has_next diff --git a/ruoyi-fastapi-backend/utils/pwd_util.py b/ruoyi-fastapi-backend/utils/pwd_util.py index c3f91ce..9fa592f 100644 --- a/ruoyi-fastapi-backend/utils/pwd_util.py +++ b/ruoyi-fastapi-backend/utils/pwd_util.py @@ -20,7 +20,7 @@ class PwdUtil: ) @classmethod - def get_password_hash(cls, input_password): + def get_password_hash(cls, input_password: str) -> str: """ 工具方法:对当前输入的密码进行加密 diff --git a/ruoyi-fastapi-backend/utils/response_util.py b/ruoyi-fastapi-backend/utils/response_util.py index 01d4632..16ce145 100644 --- a/ruoyi-fastapi-backend/utils/response_util.py +++ b/ruoyi-fastapi-backend/utils/response_util.py @@ -1,10 +1,13 @@ +from collections.abc import Mapping from datetime import datetime +from typing import Any, Optional + from fastapi import status from fastapi.encoders import jsonable_encoder from fastapi.responses import JSONResponse, Response, StreamingResponse from pydantic import BaseModel from starlette.background import BackgroundTask -from typing import Any, Dict, Mapping, Optional + from config.constant import HttpStatusConstant @@ -19,7 +22,7 @@ class ResponseUtil: msg: str = '操作成功', data: Optional[Any] = None, rows: Optional[Any] = None, - dict_content: Optional[Dict] = None, + dict_content: Optional[dict] = None, model_content: Optional[BaseModel] = None, headers: Optional[Mapping[str, str]] = None, media_type: Optional[str] = None, @@ -65,7 +68,7 @@ class ResponseUtil: msg: str = '操作失败', data: Optional[Any] = None, rows: Optional[Any] = None, - dict_content: Optional[Dict] = None, + dict_content: Optional[dict] = None, model_content: Optional[BaseModel] = None, headers: Optional[Mapping[str, str]] = None, media_type: Optional[str] = None, @@ -111,7 +114,7 @@ class ResponseUtil: msg: str = '登录信息已过期,访问系统资源失败', data: Optional[Any] = None, rows: Optional[Any] = None, - dict_content: Optional[Dict] = None, + dict_content: Optional[dict] = None, model_content: Optional[BaseModel] = None, headers: Optional[Mapping[str, str]] = None, media_type: Optional[str] = None, @@ -157,7 +160,7 @@ class ResponseUtil: msg: str = '该用户无此接口权限', data: Optional[Any] = None, rows: Optional[Any] = None, - dict_content: Optional[Dict] = None, + dict_content: Optional[dict] = None, model_content: Optional[BaseModel] = None, headers: Optional[Mapping[str, str]] = None, media_type: Optional[str] = None, @@ -203,7 +206,7 @@ class ResponseUtil: msg: str = '接口异常', data: Optional[Any] = None, rows: Optional[Any] = None, - dict_content: Optional[Dict] = None, + dict_content: Optional[dict] = None, model_content: Optional[BaseModel] = None, headers: Optional[Mapping[str, str]] = None, media_type: Optional[str] = None, diff --git a/ruoyi-fastapi-backend/utils/string_util.py b/ruoyi-fastapi-backend/utils/string_util.py index 7196bcf..756456f 100644 --- a/ruoyi-fastapi-backend/utils/string_util.py +++ b/ruoyi-fastapi-backend/utils/string_util.py @@ -1,4 +1,5 @@ -from typing import Dict, List +from typing import Union + from config.constant import CommonConstant @@ -8,7 +9,7 @@ class StringUtil: """ @classmethod - def is_blank(cls, string: str) -> bool: + def is_blank(cls, string: Union[str, None]) -> bool: """ 校验字符串是否为''或全空格 @@ -20,14 +21,10 @@ class StringUtil: str_len = len(string) if str_len == 0: return True - else: - for i in range(str_len): - if string[i] != ' ': - return False - return True + return all(string[i] == ' ' for i in range(str_len)) @classmethod - def is_empty(cls, string) -> bool: + def is_empty(cls, string: str) -> bool: """ 校验字符串是否为''或None @@ -47,17 +44,17 @@ class StringUtil: return not cls.is_empty(string) @classmethod - def is_http(cls, link: str): + def is_http(cls, link: str) -> bool: """ 判断是否为http(s)://开头 :param link: 链接 :return: 是否为http(s)://开头 """ - return link.startswith(CommonConstant.HTTP) or link.startswith(CommonConstant.HTTPS) + return link.startswith((CommonConstant.HTTP, CommonConstant.HTTPS)) @classmethod - def contains_ignore_case(cls, search_str: str, compare_str: str): + def contains_ignore_case(cls, search_str: str, compare_str: str) -> bool: """ 查找指定字符串是否包含指定字符串同时忽略大小写 @@ -70,7 +67,7 @@ class StringUtil: return False @classmethod - def contains_any_ignore_case(cls, search_str: str, compare_str_list: List[str]): + def contains_any_ignore_case(cls, search_str: str, compare_str_list: list[str]) -> bool: """ 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时忽略大小写 @@ -79,11 +76,11 @@ class StringUtil: :return: 查找结果 """ if search_str and compare_str_list: - return any([cls.contains_ignore_case(search_str, compare_str) for compare_str in compare_str_list]) + return any(cls.contains_ignore_case(search_str, compare_str) for compare_str in compare_str_list) return False @classmethod - def equals_ignore_case(cls, search_str: str, compare_str: str): + def equals_ignore_case(cls, search_str: str, compare_str: str) -> bool: """ 比较两个字符串是否相等同时忽略大小写 @@ -96,7 +93,7 @@ class StringUtil: return False @classmethod - def equals_any_ignore_case(cls, search_str: str, compare_str_list: List[str]): + def equals_any_ignore_case(cls, search_str: str, compare_str_list: list[str]) -> bool: """ 比较指定字符串是否与指定字符串列表中的任意一个字符串相等同时忽略大小写 @@ -105,11 +102,11 @@ class StringUtil: :return: 比较结果 """ if search_str and compare_str_list: - return any([cls.equals_ignore_case(search_str, compare_str) for compare_str in compare_str_list]) + return any(cls.equals_ignore_case(search_str, compare_str) for compare_str in compare_str_list) return False @classmethod - def startswith_case(cls, search_str: str, compare_str: str): + def startswith_case(cls, search_str: str, compare_str: str) -> bool: """ 查找指定字符串是否以指定字符串开头 @@ -122,7 +119,7 @@ class StringUtil: return False @classmethod - def startswith_any_case(cls, search_str: str, compare_str_list: List[str]): + def startswith_any_case(cls, search_str: str, compare_str_list: list[str]) -> bool: """ 查找指定字符串是否以指定字符串列表中的任意一个字符串开头 @@ -131,7 +128,7 @@ class StringUtil: :return: 查找结果 """ if search_str and compare_str_list: - return any([cls.startswith_case(search_str, compare_str) for compare_str in compare_str_list]) + return any(cls.startswith_case(search_str, compare_str) for compare_str in compare_str_list) return False @classmethod @@ -155,7 +152,7 @@ class StringUtil: return ''.join(result) @classmethod - def get_mapping_value_by_key_ignore_case(cls, mapping: Dict[str, str], key: str) -> str: + def get_mapping_value_by_key_ignore_case(cls, mapping: dict[str, str], key: str) -> str: """ 根据忽略大小写的键获取字典中的对应的值 @@ -166,5 +163,5 @@ class StringUtil: for k, v in mapping.items(): if key.lower() == k.lower(): return v - + return '' diff --git a/ruoyi-fastapi-backend/utils/template_util.py b/ruoyi-fastapi-backend/utils/template_util.py index afe5c41..b5163a5 100644 --- a/ruoyi-fastapi-backend/utils/template_util.py +++ b/ruoyi-fastapi-backend/utils/template_util.py @@ -1,12 +1,14 @@ import json import os from datetime import datetime +from typing import Any + from jinja2 import Environment, FileSystemLoader -from typing import Dict, List, Set + from config.constant import GenConstant from config.env import DataBaseConfig from exceptions.exception import ServiceWarning -from module_generator.entity.vo.gen_vo import GenTableModel, GenTableColumnModel +from module_generator.entity.vo.gen_vo import GenTableColumnModel, GenTableModel from utils.common_util import CamelCaseUtil, SnakeCaseUtil from utils.string_util import StringUtil @@ -17,7 +19,7 @@ class TemplateInitializer: """ @classmethod - def init_jinja2(cls): + def init_jinja2(cls) -> Environment: """ 初始化 Jinja2 模板引擎 @@ -40,7 +42,7 @@ class TemplateInitializer: ) return env except Exception as e: - raise RuntimeError(f'初始化Jinja2模板引擎失败: {e}') + raise RuntimeError(f'初始化Jinja2模板引擎失败: {e}') from e class TemplateUtils: @@ -54,7 +56,7 @@ class TemplateUtils: DEFAULT_PARENT_MENU_ID = '3' @classmethod - def prepare_context(cls, gen_table: GenTableModel): + def prepare_context(cls, gen_table: GenTableModel) -> dict[str, Any]: """ 准备模板变量 @@ -106,7 +108,7 @@ class TemplateUtils: return context @classmethod - def set_menu_context(cls, context: Dict, gen_table: GenTableModel): + def set_menu_context(cls, context: dict, gen_table: GenTableModel) -> None: """ 设置菜单上下文 @@ -119,7 +121,7 @@ class TemplateUtils: context['parentMenuId'] = cls.get_parent_menu_id(params_obj) @classmethod - def set_tree_context(cls, context: Dict, gen_table: GenTableModel): + def set_tree_context(cls, context: dict, gen_table: GenTableModel) -> None: """ 设置树形结构上下文 @@ -135,7 +137,7 @@ class TemplateUtils: context['expandColumn'] = cls.get_expand_column(gen_table) @classmethod - def set_sub_context(cls, context: Dict, gen_table: GenTableModel): + def set_sub_context(cls, context: dict, gen_table: GenTableModel) -> None: """ 设置子表上下文 @@ -157,7 +159,7 @@ class TemplateUtils: context['subclassName'] = sub_class_name.lower() @classmethod - def get_template_list(cls, tpl_category: str, tpl_web_type: str): + def get_template_list(cls, tpl_category: str, tpl_web_type: str) -> list[str]: """ 获取模板列表 @@ -187,7 +189,7 @@ class TemplateUtils: return templates @classmethod - def get_file_name(cls, template: List[str], gen_table: GenTableModel): + def get_file_name(cls, template: list[str], gen_table: GenTableModel) -> str: """ 根据模板生成文件名 @@ -204,24 +206,24 @@ class TemplateUtils: if 'controller.py.jinja2' in template: return f'{python_path}/controller/{business_name}_controller.py' - elif 'dao.py.jinja2' in template: + if 'dao.py.jinja2' in template: return f'{python_path}/dao/{business_name}_dao.py' - elif 'do.py.jinja2' in template: + if 'do.py.jinja2' in template: return f'{python_path}/entity/do/{business_name}_do.py' - elif 'service.py.jinja2' in template: + if 'service.py.jinja2' in template: return f'{python_path}/service/{business_name}_service.py' - elif 'vo.py.jinja2' in template: + if 'vo.py.jinja2' in template: return f'{python_path}/entity/vo/{business_name}_vo.py' - elif 'sql.jinja2' in template: + if 'sql.jinja2' in template: return f'{cls.BACKEND_PROJECT_PATH}/sql/{business_name}_menu.sql' - elif 'api.js.jinja2' in template: + if 'api.js.jinja2' in template: return f'{vue_path}/api/{module_name}/{business_name}.js' - elif 'index.vue.jinja2' in template or 'index-tree.vue.jinja2' in template: + if 'index.vue.jinja2' in template or 'index-tree.vue.jinja2' in template: return f'{vue_path}/views/{module_name}/{business_name}/index.vue' return '' @classmethod - def get_package_prefix(cls, package_name: str): + def get_package_prefix(cls, package_name: str) -> str: """ 获取包前缀 @@ -231,7 +233,7 @@ class TemplateUtils: return package_name[: package_name.rfind('.')] @classmethod - def get_vo_import_list(cls, gen_table: GenTableModel): + def get_vo_import_list(cls, gen_table: GenTableModel) -> list[str]: """ 获取vo模板导入包列表 @@ -255,7 +257,7 @@ class TemplateUtils: return cls.merge_same_imports(list(import_list), 'from datetime import') @classmethod - def get_do_import_list(cls, gen_table: GenTableModel): + def get_do_import_list(cls, gen_table: GenTableModel) -> list[str]: """ 获取do模板导入包列表 @@ -295,7 +297,7 @@ class TemplateUtils: return column_type @classmethod - def merge_same_imports(cls, imports: List[str], import_start: str) -> List[str]: + def merge_same_imports(cls, imports: list[str], import_start: str) -> list[str]: """ 合并相同的导入语句 @@ -319,7 +321,7 @@ class TemplateUtils: return merged_imports @classmethod - def get_dicts(cls, gen_table: GenTableModel): + def get_dicts(cls, gen_table: GenTableModel) -> str: """ 获取字典列表 @@ -334,7 +336,7 @@ class TemplateUtils: return ', '.join(dicts) @classmethod - def add_dicts(cls, dicts: Set[str], columns: List[GenTableColumnModel]): + def add_dicts(cls, dicts: set[str], columns: list[GenTableColumnModel]) -> None: """ 添加字典列表 @@ -353,7 +355,7 @@ class TemplateUtils: dicts.add(f"'{column.dict_type}'") @classmethod - def get_permission_prefix(cls, module_name: str, business_name: str): + def get_permission_prefix(cls, module_name: str, business_name: str) -> str: """ 获取权限前缀 @@ -364,7 +366,7 @@ class TemplateUtils: return f'{module_name}:{business_name}' @classmethod - def get_parent_menu_id(cls, params_obj: Dict): + def get_parent_menu_id(cls, params_obj: dict) -> str: """ 获取上级菜单ID @@ -376,7 +378,7 @@ class TemplateUtils: return cls.DEFAULT_PARENT_MENU_ID @classmethod - def get_tree_code(cls, params_obj: Dict): + def get_tree_code(cls, params_obj: dict) -> str: """ 获取树编码 @@ -388,7 +390,7 @@ class TemplateUtils: return '' @classmethod - def get_tree_parent_code(cls, params_obj: Dict): + def get_tree_parent_code(cls, params_obj: dict) -> str: """ 获取树父编码 @@ -400,7 +402,7 @@ class TemplateUtils: return '' @classmethod - def get_tree_name(cls, params_obj: Dict): + def get_tree_name(cls, params_obj: dict) -> str: """ 获取树名称 @@ -412,7 +414,7 @@ class TemplateUtils: return '' @classmethod - def get_expand_column(cls, gen_table: GenTableModel): + def get_expand_column(cls, gen_table: GenTableModel) -> int: """ 获取展开列 @@ -442,7 +444,7 @@ class TemplateUtils: return parts[0] + ''.join(word.capitalize() for word in parts[1:]) @classmethod - def get_sqlalchemy_type(cls, column_type: str): + def get_sqlalchemy_type(cls, column_type: str) -> str: """ 获取SQLAlchemy类型 diff --git a/ruoyi-fastapi-backend/utils/time_format_util.py b/ruoyi-fastapi-backend/utils/time_format_util.py index bfb0481..71e9f6a 100644 --- a/ruoyi-fastapi-backend/utils/time_format_util.py +++ b/ruoyi-fastapi-backend/utils/time_format_util.py @@ -1,10 +1,11 @@ from copy import deepcopy -from datetime import datetime +from datetime import date, datetime +from typing import Any, Union + from dateutil.parser import parse -from typing import Dict, List, Union -def object_format_datetime(obj): +def object_format_datetime(obj: Any) -> Any: """ :param obj: 输入一个对象 :return:对目标对象所有datetime类型的属性格式化 @@ -16,7 +17,7 @@ def object_format_datetime(obj): return obj -def list_format_datetime(lst): +def list_format_datetime(lst: list[Any]) -> list[Any]: """ :param lst: 输入一个嵌套对象的列表 :return: 对目标列表中所有对象的datetime类型的属性格式化 @@ -29,7 +30,7 @@ def list_format_datetime(lst): return lst -def format_datetime_dict_list(dicts): +def format_datetime_dict_list(dicts: list[dict]) -> list[dict]: """ 递归遍历嵌套字典,并将 datetime 值转换为字符串格式 @@ -61,27 +62,27 @@ class TimeFormatUtil: """ @classmethod - def format_time(cls, time_info: Union[str, datetime], format: str = '%Y-%m-%d %H:%M:%S'): + def format_time(cls, time_info: Union[str, datetime], fmt: str = '%Y-%m-%d %H:%M:%S') -> str: """ 格式化时间字符串或datetime对象为指定格式 :param time_info: 时间字符串或datetime对象 - :param format: 格式化格式,默认为'%Y-%m-%d %H:%M:%S' + :param fmt: 格式化格式,默认为'%Y-%m-%d %H:%M:%S' :return: 格式化后的时间字符串 """ if isinstance(time_info, datetime): - format_date = time_info.strftime(format) + format_date = time_info.strftime(fmt) else: try: date = parse(time_info) - format_date = date.strftime(format) + format_date = date.strftime(fmt) except Exception: format_date = time_info return format_date @classmethod - def parse_date(cls, time_str: str): + def parse_date(cls, time_str: str) -> Union[date, str]: """ 解析时间字符串提取日期部分 @@ -95,44 +96,44 @@ class TimeFormatUtil: return time_str @classmethod - def format_time_dict(cls, time_dict: Dict, format: str = '%Y-%m-%d %H:%M:%S'): + def format_time_dict(cls, time_dict: dict, fmt: str = '%Y-%m-%d %H:%M:%S') -> dict: """ 格式化时间字典 :param time_dict: 时间字典 - :param format: 格式化格式,默认为'%Y-%m-%d %H:%M:%S' + :param fmt: 格式化格式,默认为'%Y-%m-%d %H:%M:%S' :return: 格式化后的时间字典 """ copy_time_dict = deepcopy(time_dict) for k, v in copy_time_dict.items(): if isinstance(v, (str, datetime)): - copy_time_dict[k] = cls.format_time(v, format) + copy_time_dict[k] = cls.format_time(v, fmt) elif isinstance(v, dict): - copy_time_dict[k] = cls.format_time_dict(v, format) + copy_time_dict[k] = cls.format_time_dict(v, fmt) elif isinstance(v, list): - copy_time_dict[k] = cls.format_time_list(v, format) + copy_time_dict[k] = cls.format_time_list(v, fmt) else: copy_time_dict[k] = v return copy_time_dict @classmethod - def format_time_list(cls, time_list: List, format: str = '%Y-%m-%d %H:%M:%S'): + def format_time_list(cls, time_list: list, fmt: str = '%Y-%m-%d %H:%M:%S') -> list: """ 格式化时间列表 :param time_list: 时间列表 - :param format: 格式化格式,默认为'%Y-%m-%d %H:%M:%S' + :param fmt: 格式化格式,默认为'%Y-%m-%d %H:%M:%S' :return: 格式化后的时间列表 """ format_time_list = [] for item in time_list: if isinstance(item, (str, datetime)): - format_item = cls.format_time(item, format) + format_item = cls.format_time(item, fmt) elif isinstance(item, dict): - format_item = cls.format_time_dict(item, format) + format_item = cls.format_time_dict(item, fmt) elif isinstance(item, list): - format_item = cls.format_time_list(item, format) + format_item = cls.format_time_list(item, fmt) else: format_item = item diff --git a/ruoyi-fastapi-backend/utils/upload_util.py b/ruoyi-fastapi-backend/utils/upload_util.py index 726789e..c979a14 100644 --- a/ruoyi-fastapi-backend/utils/upload_util.py +++ b/ruoyi-fastapi-backend/utils/upload_util.py @@ -1,7 +1,11 @@ import os import random +from collections.abc import AsyncGenerator from datetime import datetime + +import aiofiles from fastapi import UploadFile + from config.env import UploadConfig @@ -11,7 +15,7 @@ class UploadUtil: """ @classmethod - def generate_random_number(cls): + def generate_random_number(cls) -> str: """ 生成3位数字构成的字符串 @@ -22,7 +26,7 @@ class UploadUtil: return f'{random_number:03}' @classmethod - def check_file_exists(cls, filepath: str): + def check_file_exists(cls, filepath: str) -> bool: """ 检查文件是否存在 @@ -32,7 +36,7 @@ class UploadUtil: return os.path.exists(filepath) @classmethod - def check_file_extension(cls, file: UploadFile): + def check_file_extension(cls, file: UploadFile) -> bool: """ 检查文件后缀是否合法 @@ -40,12 +44,11 @@ class UploadUtil: :return: 校验结果 """ file_extension = file.filename.rsplit('.', 1)[-1] - if file_extension in UploadConfig.DEFAULT_ALLOWED_EXTENSION: - return True - return False + + return file_extension in UploadConfig.DEFAULT_ALLOWED_EXTENSION @classmethod - def check_file_timestamp(cls, filename: str): + def check_file_timestamp(cls, filename: str) -> bool: """ 校验文件时间戳是否合法 @@ -60,19 +63,17 @@ class UploadUtil: return False @classmethod - def check_file_machine(cls, filename: str): + def check_file_machine(cls, filename: str) -> bool: """ 校验文件机器码是否合法 :param filename: 文件名称 :return: 校验结果 """ - if filename.rsplit('.', 1)[0][-4] == UploadConfig.UPLOAD_MACHINE: - return True - return False + return filename.rsplit('.', 1)[0][-4] == UploadConfig.UPLOAD_MACHINE @classmethod - def check_file_random_code(cls, filename: str): + def check_file_random_code(cls, filename: str) -> bool: """ 校验文件随机码是否合法 @@ -80,23 +81,23 @@ class UploadUtil: :return: 校验结果 """ valid_code_list = [f'{i:03}' for i in range(1, 999)] - if filename.rsplit('.', 1)[0][-3:] in valid_code_list: - return True - return False + + return filename.rsplit('.', 1)[0][-3:] in valid_code_list @classmethod - def generate_file(cls, filepath: str): + async def generate_file(cls, filepath: str) -> AsyncGenerator[bytes, None]: """ 根据文件生成二进制数据 :param filepath: 文件路径 :yield: 二进制数据 """ - with open(filepath, 'rb') as response_file: - yield from response_file + async with aiofiles.open(filepath, 'rb') as response_file: + async for chunk in response_file: + yield chunk @classmethod - def delete_file(cls, filepath: str): + def delete_file(cls, filepath: str) -> None: """ 根据文件路径删除对应文件 From a3355e25453ea2210f1b849e4c6e3f182a7fadbd Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 5 Dec 2025 15:02:04 +0800 Subject: [PATCH 02/49] =?UTF-8?q?refactor&feat:=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?common=E6=A8=A1=E5=9D=97=EF=BC=8C=E5=8E=9Fannotation=E3=80=81as?= =?UTF-8?q?pect=E3=80=81constant=E3=80=81enums=E6=A8=A1=E5=9D=97=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E8=87=B3common=E6=A8=A1=E5=9D=97=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{module_admin => common}/annotation/log_annotation.py | 2 +- .../annotation/pydantic_annotation.py | 0 .../{module_admin => common}/aspect/data_scope.py | 0 .../{module_admin => common}/aspect/interface_auth.py | 0 ruoyi-fastapi-backend/{config => common}/constant.py | 0 ruoyi-fastapi-backend/{config => common}/enums.py | 0 .../module_admin/controller/cache_controller.py | 2 +- .../module_admin/controller/captcha_controller.py | 2 +- .../module_admin/controller/config_controller.py | 6 +++--- .../module_admin/controller/dept_controller.py | 8 ++++---- .../module_admin/controller/dict_controller.py | 6 +++--- .../module_admin/controller/job_controller.py | 6 +++--- .../module_admin/controller/log_controller.py | 6 +++--- .../module_admin/controller/login_controller.py | 4 ++-- .../module_admin/controller/menu_controller.py | 6 +++--- .../module_admin/controller/notice_controller.py | 6 +++--- .../module_admin/controller/online_controller.py | 6 +++--- .../module_admin/controller/post_controller.py | 6 +++--- .../module_admin/controller/role_controller.py | 8 ++++---- .../module_admin/controller/server_controller.py | 2 +- .../module_admin/controller/user_controller.py | 8 ++++---- .../module_admin/service/cache_service.py | 2 +- .../module_admin/service/config_service.py | 4 ++-- .../module_admin/service/dept_service.py | 2 +- .../module_admin/service/dict_service.py | 4 ++-- ruoyi-fastapi-backend/module_admin/service/job_service.py | 2 +- .../module_admin/service/login_service.py | 4 ++-- .../module_admin/service/menu_service.py | 2 +- .../module_admin/service/notice_service.py | 2 +- .../module_admin/service/online_service.py | 2 +- .../module_admin/service/post_service.py | 2 +- .../module_admin/service/role_service.py | 2 +- .../module_admin/service/user_service.py | 2 +- .../module_generator/controller/gen_controller.py | 6 +++--- .../module_generator/entity/vo/gen_vo.py | 2 +- .../module_generator/service/gen_service.py | 2 +- .../templates/python/controller.py.jinja2 | 6 +++--- .../module_generator/templates/python/service.py.jinja2 | 2 +- ruoyi-fastapi-backend/utils/gen_util.py | 2 +- ruoyi-fastapi-backend/utils/response_util.py | 2 +- ruoyi-fastapi-backend/utils/string_util.py | 2 +- ruoyi-fastapi-backend/utils/template_util.py | 2 +- 42 files changed, 70 insertions(+), 70 deletions(-) rename ruoyi-fastapi-backend/{module_admin => common}/annotation/log_annotation.py (99%) rename ruoyi-fastapi-backend/{module_admin => common}/annotation/pydantic_annotation.py (100%) rename ruoyi-fastapi-backend/{module_admin => common}/aspect/data_scope.py (100%) rename ruoyi-fastapi-backend/{module_admin => common}/aspect/interface_auth.py (100%) rename ruoyi-fastapi-backend/{config => common}/constant.py (100%) rename ruoyi-fastapi-backend/{config => common}/enums.py (100%) diff --git a/ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py b/ruoyi-fastapi-backend/common/annotation/log_annotation.py similarity index 99% rename from ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py rename to ruoyi-fastapi-backend/common/annotation/log_annotation.py index 0c48512..a0df36a 100644 --- a/ruoyi-fastapi-backend/module_admin/annotation/log_annotation.py +++ b/ruoyi-fastapi-backend/common/annotation/log_annotation.py @@ -15,7 +15,7 @@ from starlette.status import HTTP_200_OK from typing_extensions import ParamSpec from user_agents import parse -from config.enums import BusinessType +from common.enums import BusinessType from config.env import AppConfig from exceptions.exception import LoginException, ServiceException, ServiceWarning from module_admin.entity.vo.log_vo import LogininforModel, OperLogModel diff --git a/ruoyi-fastapi-backend/module_admin/annotation/pydantic_annotation.py b/ruoyi-fastapi-backend/common/annotation/pydantic_annotation.py similarity index 100% rename from ruoyi-fastapi-backend/module_admin/annotation/pydantic_annotation.py rename to ruoyi-fastapi-backend/common/annotation/pydantic_annotation.py diff --git a/ruoyi-fastapi-backend/module_admin/aspect/data_scope.py b/ruoyi-fastapi-backend/common/aspect/data_scope.py similarity index 100% rename from ruoyi-fastapi-backend/module_admin/aspect/data_scope.py rename to ruoyi-fastapi-backend/common/aspect/data_scope.py diff --git a/ruoyi-fastapi-backend/module_admin/aspect/interface_auth.py b/ruoyi-fastapi-backend/common/aspect/interface_auth.py similarity index 100% rename from ruoyi-fastapi-backend/module_admin/aspect/interface_auth.py rename to ruoyi-fastapi-backend/common/aspect/interface_auth.py diff --git a/ruoyi-fastapi-backend/config/constant.py b/ruoyi-fastapi-backend/common/constant.py similarity index 100% rename from ruoyi-fastapi-backend/config/constant.py rename to ruoyi-fastapi-backend/common/constant.py diff --git a/ruoyi-fastapi-backend/config/enums.py b/ruoyi-fastapi-backend/common/enums.py similarity index 100% rename from ruoyi-fastapi-backend/config/enums.py rename to ruoyi-fastapi-backend/common/enums.py diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index 7ade706..a5ff8ca 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -2,7 +2,7 @@ from typing import Annotated from fastapi import APIRouter, Depends, Path, Request, Response -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.service.cache_service import CacheService from module_admin.service.login_service import LoginService diff --git a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py index 479375c..f1ef6c4 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py @@ -3,7 +3,7 @@ from datetime import timedelta from fastapi import APIRouter, Request, Response -from config.enums import RedisInitKeyConfig +from common.enums import RedisInitKeyConfig from module_admin.entity.vo.login_vo import CaptchaCode from module_admin.service.captcha_service import CaptchaService from utils.log_util import logger diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index 640966c..ac8c811 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.config_service import ConfigService diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index d5638c7..a3a98e6 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -5,11 +5,11 @@ from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.data_scope import GetDataScope +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.data_scope import GetDataScope -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.dept_service import DeptService diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index 2822591..9a719ae 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.dict_vo import ( DeleteDictDataModel, DeleteDictTypeModel, diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index 0b4306d..efe9021 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.job_vo import ( DeleteJobLogModel, DeleteJobModel, diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index 39541be..c64943e 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -3,10 +3,10 @@ from typing import Annotated from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.log_vo import ( DeleteLoginLogModel, DeleteOperLogModel, diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 0accf07..6df7872 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -6,10 +6,10 @@ import jwt from fastapi import APIRouter, Depends, Request, Response from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType, RedisInitKeyConfig +from common.annotation.log_annotation import Log +from common.enums import BusinessType, RedisInitKeyConfig from config.env import AppConfig, JwtConfig from config.get_db import get_db -from module_admin.annotation.log_annotation import Log from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.login_vo import Token, UserLogin, UserRegister from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index 4cf4d76..0359ab0 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService diff --git a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py index 9a01737..8dcb2cf 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py @@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index 70c731c..4fde252 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -3,10 +3,10 @@ from typing import Annotated from fastapi import APIRouter, Depends, Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineQueryModel from module_admin.service.login_service import LoginService from module_admin.service.online_service import OnlineService diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index 475849d..64368ae 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -5,10 +5,10 @@ from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index 5e52133..c13bf55 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -5,11 +5,11 @@ from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.data_scope import GetDataScope +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.data_scope import GetDataScope -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.role_vo import AddRoleModel, DeleteRoleModel, RoleModel, RolePageQueryModel from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserRolePageQueryModel diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index 2258e83..ed1bffb 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -1,6 +1,6 @@ from fastapi import APIRouter, Depends, Request, Response -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.server_vo import ServerMonitorModel from module_admin.service.login_service import LoginService from module_admin.service.server_service import ServerService diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index c36604b..b8cdc5a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -7,12 +7,12 @@ from fastapi import APIRouter, Depends, File, Form, Path, Query, Request, Respon from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.data_scope import GetDataScope +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.env import UploadConfig from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.data_scope import GetDataScope -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.user_vo import ( AddUserModel, diff --git a/ruoyi-fastapi-backend/module_admin/service/cache_service.py b/ruoyi-fastapi-backend/module_admin/service/cache_service.py index 27619a8..6ffb2eb 100644 --- a/ruoyi-fastapi-backend/module_admin/service/cache_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/cache_service.py @@ -1,6 +1,6 @@ from fastapi import Request -from config.enums import RedisInitKeyConfig +from common.enums import RedisInitKeyConfig from config.get_redis import RedisUtil from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/module_admin/service/config_service.py b/ruoyi-fastapi-backend/module_admin/service/config_service.py index 20a4968..3c45a5f 100644 --- a/ruoyi-fastapi-backend/module_admin/service/config_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/config_service.py @@ -4,8 +4,8 @@ from fastapi import Request from redis import asyncio as aioredis from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant -from config.enums import RedisInitKeyConfig +from common.constant import CommonConstant +from common.enums import RedisInitKeyConfig from exceptions.exception import ServiceException from module_admin.dao.config_dao import ConfigDao from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/module_admin/service/dept_service.py b/ruoyi-fastapi-backend/module_admin/service/dept_service.py index 247ee6b..186ea32 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dept_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dept_service.py @@ -3,7 +3,7 @@ from typing import Any from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant +from common.constant import CommonConstant from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.dept_dao import DeptDao from module_admin.entity.do.dept_do import SysDept diff --git a/ruoyi-fastapi-backend/module_admin/service/dict_service.py b/ruoyi-fastapi-backend/module_admin/service/dict_service.py index 9bd556e..d92fcbe 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dict_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dict_service.py @@ -6,8 +6,8 @@ from fastapi import Request from redis import asyncio as aioredis from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant -from config.enums import RedisInitKeyConfig +from common.constant import CommonConstant +from common.enums import RedisInitKeyConfig from exceptions.exception import ServiceException from module_admin.dao.dict_dao import DictDataDao, DictTypeDao from module_admin.entity.do.dict_do import SysDictData diff --git a/ruoyi-fastapi-backend/module_admin/service/job_service.py b/ruoyi-fastapi-backend/module_admin/service/job_service.py index 7e584ce..83a9282 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_service.py @@ -3,7 +3,7 @@ from typing import Any, Union from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant, JobConstant +from common.constant import CommonConstant, JobConstant from config.get_scheduler import SchedulerUtil from exceptions.exception import ServiceException from module_admin.dao.job_dao import JobDao diff --git a/ruoyi-fastapi-backend/module_admin/service/login_service.py b/ruoyi-fastapi-backend/module_admin/service/login_service.py index f55eaa8..6dfe31b 100644 --- a/ruoyi-fastapi-backend/module_admin/service/login_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/login_service.py @@ -10,8 +10,8 @@ from jwt.exceptions import InvalidTokenError from sqlalchemy import Row from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant, MenuConstant -from config.enums import RedisInitKeyConfig +from common.constant import CommonConstant, MenuConstant +from common.enums import RedisInitKeyConfig from config.env import AppConfig, JwtConfig from config.get_db import get_db from exceptions.exception import AuthException, LoginException, ServiceException diff --git a/ruoyi-fastapi-backend/module_admin/service/menu_service.py b/ruoyi-fastapi-backend/module_admin/service/menu_service.py index 6c403d5..43526bd 100644 --- a/ruoyi-fastapi-backend/module_admin/service/menu_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/menu_service.py @@ -3,7 +3,7 @@ from typing import Any, Optional from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant, MenuConstant +from common.constant import CommonConstant, MenuConstant from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.menu_dao import MenuDao from module_admin.dao.role_dao import RoleDao diff --git a/ruoyi-fastapi-backend/module_admin/service/notice_service.py b/ruoyi-fastapi-backend/module_admin/service/notice_service.py index 51452e6..5949887 100644 --- a/ruoyi-fastapi-backend/module_admin/service/notice_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/notice_service.py @@ -2,7 +2,7 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant +from common.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.notice_dao import NoticeDao from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/module_admin/service/online_service.py b/ruoyi-fastapi-backend/module_admin/service/online_service.py index 2ba06c4..cf25d4f 100644 --- a/ruoyi-fastapi-backend/module_admin/service/online_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/online_service.py @@ -3,7 +3,7 @@ from typing import Any import jwt from fastapi import Request -from config.enums import RedisInitKeyConfig +from common.enums import RedisInitKeyConfig from config.env import JwtConfig from exceptions.exception import ServiceException from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/module_admin/service/post_service.py b/ruoyi-fastapi-backend/module_admin/service/post_service.py index f82016e..cdf93ef 100644 --- a/ruoyi-fastapi-backend/module_admin/service/post_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/post_service.py @@ -2,7 +2,7 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant +from common.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.post_dao import PostDao from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index a0eaf91..4662e0d 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -2,7 +2,7 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant +from common.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.role_dao import RoleDao from module_admin.dao.user_dao import UserDao diff --git a/ruoyi-fastapi-backend/module_admin/service/user_service.py b/ruoyi-fastapi-backend/module_admin/service/user_service.py index fe2bf8e..aaefc00 100644 --- a/ruoyi-fastapi-backend/module_admin/service/user_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/user_service.py @@ -6,7 +6,7 @@ import pandas as pd from fastapi import Request, UploadFile from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant +from common.constant import CommonConstant from exceptions.exception import ServiceException from module_admin.dao.user_dao import UserDao from module_admin.entity.do.user_do import SysUserRole diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index 9a22bc8..6f5d4c5 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -5,11 +5,11 @@ from fastapi import APIRouter, Depends, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckRoleInterfaceAuth, CheckUserInterfaceAuth +from common.enums import BusinessType from config.env import GenConfig from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckRoleInterfaceAuth, CheckUserInterfaceAuth from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService from module_generator.entity.vo.gen_vo import DeleteGenTableModel, EditGenTableModel, GenTablePageQueryModel diff --git a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py index d821287..c43b227 100644 --- a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py +++ b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py @@ -5,7 +5,7 @@ from pydantic import BaseModel, ConfigDict, Field, model_validator from pydantic.alias_generators import to_camel from pydantic_validation_decorator import NotBlank -from config.constant import GenConstant +from common.constant import GenConstant from utils.string_util import StringUtil diff --git a/ruoyi-fastapi-backend/module_generator/service/gen_service.py b/ruoyi-fastapi-backend/module_generator/service/gen_service.py index a77cd85..a46bc7b 100644 --- a/ruoyi-fastapi-backend/module_generator/service/gen_service.py +++ b/ruoyi-fastapi-backend/module_generator/service/gen_service.py @@ -10,7 +10,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlglot import parse as sqlglot_parse from sqlglot.expressions import Add, Alter, Create, Delete, Drop, Expression, Insert, Table, TruncateTable, Update -from config.constant import GenConstant +from common.constant import GenConstant from config.env import DataBaseConfig, GenConfig from exceptions.exception import ServiceException from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index fa9de0e..4c33ca9 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -17,10 +17,10 @@ from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession -from config.enums import BusinessType +from common.annotation.log_annotation import Log +from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.enums import BusinessType from config.get_db import get_db -from module_admin.annotation.log_annotation import Log -from module_admin.aspect.interface_auth import CheckUserInterfaceAuth from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.login_service import LoginService from {{ packageName }}.service.{{ businessName }}_service import {{ BusinessName }}Service diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 index a75563e..5608b55 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 @@ -9,7 +9,7 @@ from fastapi import Request {% endif %} from sqlalchemy.ext.asyncio import AsyncSession -from config.constant import CommonConstant +from common.constant import CommonConstant from exceptions.exception import ServiceException from {{ packageName }}.dao.{{ businessName }}_dao import {{ BusinessName }}Dao from module_admin.entity.vo.common_vo import CrudResponseModel diff --git a/ruoyi-fastapi-backend/utils/gen_util.py b/ruoyi-fastapi-backend/utils/gen_util.py index 68d3419..c08ceec 100644 --- a/ruoyi-fastapi-backend/utils/gen_util.py +++ b/ruoyi-fastapi-backend/utils/gen_util.py @@ -1,7 +1,7 @@ import re from datetime import datetime -from config.constant import GenConstant +from common.constant import GenConstant from config.env import GenConfig from module_generator.entity.vo.gen_vo import GenTableColumnModel, GenTableModel from utils.string_util import StringUtil diff --git a/ruoyi-fastapi-backend/utils/response_util.py b/ruoyi-fastapi-backend/utils/response_util.py index 16ce145..ebf85c3 100644 --- a/ruoyi-fastapi-backend/utils/response_util.py +++ b/ruoyi-fastapi-backend/utils/response_util.py @@ -8,7 +8,7 @@ from fastapi.responses import JSONResponse, Response, StreamingResponse from pydantic import BaseModel from starlette.background import BackgroundTask -from config.constant import HttpStatusConstant +from common.constant import HttpStatusConstant class ResponseUtil: diff --git a/ruoyi-fastapi-backend/utils/string_util.py b/ruoyi-fastapi-backend/utils/string_util.py index 756456f..d14d660 100644 --- a/ruoyi-fastapi-backend/utils/string_util.py +++ b/ruoyi-fastapi-backend/utils/string_util.py @@ -1,6 +1,6 @@ from typing import Union -from config.constant import CommonConstant +from common.constant import CommonConstant class StringUtil: diff --git a/ruoyi-fastapi-backend/utils/template_util.py b/ruoyi-fastapi-backend/utils/template_util.py index b5163a5..9983fa5 100644 --- a/ruoyi-fastapi-backend/utils/template_util.py +++ b/ruoyi-fastapi-backend/utils/template_util.py @@ -5,7 +5,7 @@ from typing import Any from jinja2 import Environment, FileSystemLoader -from config.constant import GenConstant +from common.constant import GenConstant from config.env import DataBaseConfig from exceptions.exception import ServiceWarning from module_generator.entity.vo.gen_vo import GenTableColumnModel, GenTableModel From f5ec612850059347d6793b23df3be12e968c4a00 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:54:09 +0800 Subject: [PATCH 03/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E4=B8=8A=E4=B8=8B=E6=96=87=E7=AE=A1=E7=90=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/common/context.py | 100 ++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 ruoyi-fastapi-backend/common/context.py diff --git a/ruoyi-fastapi-backend/common/context.py b/ruoyi-fastapi-backend/common/context.py new file mode 100644 index 0000000..0e325a3 --- /dev/null +++ b/ruoyi-fastapi-backend/common/context.py @@ -0,0 +1,100 @@ +import re +from contextvars import ContextVar, Token +from typing import Literal, Optional, Union + +from exceptions.exception import LoginException +from module_admin.entity.vo.user_vo import CurrentUserModel + +# 定义上下文变量 +# 存储当前请求的编译后的排除路由模式列表 +current_exclude_patterns: ContextVar[ + Optional[ + list[ + dict[str, Union[str, list[Literal['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']], re.Pattern]] + ] + ] +] = ContextVar('current_exclude_patterns', default=None) +# 存储当前用户信息 +current_user: ContextVar[Optional[CurrentUserModel]] = ContextVar('current_user', default=None) + + +class RequestContext: + """ + 请求上下文管理类,用于设置和清理上下文变量 + """ + + @staticmethod + def set_current_exclude_patterns( + exclude_patterns: list[ + dict[str, Union[str, list[Literal['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']], re.Pattern]] + ], + ) -> Token: + """ + 设置当前请求的编译后的排除路由模式列表 + + :param exclude_patterns: 编译后的排除路由模式列表 + :return: 上下文变量令牌,用于重置 + """ + return current_exclude_patterns.set(exclude_patterns) + + @staticmethod + def get_current_exclude_patterns() -> list[ + dict[str, Union[str, list[Literal['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']], re.Pattern]] + ]: + """ + 获取当前请求的编译后的排除路由模式列表 + + :return: 编译后的排除路由模式列表 + """ + _exclude_patterns = current_exclude_patterns.get() + if _exclude_patterns is None: + _exclude_patterns = [] + return _exclude_patterns + + @staticmethod + def set_current_user(user: CurrentUserModel) -> Token: + """ + 设置当前用户信息 + + :param user: 用户信息 + :return: 上下文变量令牌,用于重置 + """ + return current_user.set(user) + + @staticmethod + def get_current_user() -> CurrentUserModel: + """ + 获取当前用户信息 + + :return: 用户信息 + """ + _current_user = current_user.get() + if _current_user is None: + raise LoginException(data='', message='当前用户信息为空,请检查是否已登录') + return _current_user + + @staticmethod + def reset_current_exclude_patterns(token: Token) -> None: + """ + 重置当前请求的编译后的排除路由模式列表 + + :param token: 设置编译后的排除路由模式列表时返回的令牌 + """ + current_exclude_patterns.reset(token) + + @staticmethod + def reset_current_user(token: Token) -> None: + """ + 重置当前用户信息 + + :param token: 设置用户信息时返回的令牌 + """ + current_user.reset(token) + + @staticmethod + def clear_all() -> None: + """ + 清除所有上下文变量 + """ + current_exclude_patterns.set(None) + current_user.set(None) From 9114d6530895448d6041612f6873d94f2ff27e52 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:55:46 +0800 Subject: [PATCH 04/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EPreAuthDependen?= =?UTF-8?q?cy=E5=92=8CCurrentUserDependency=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/aspect/pre_auth.py | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 ruoyi-fastapi-backend/common/aspect/pre_auth.py diff --git a/ruoyi-fastapi-backend/common/aspect/pre_auth.py b/ruoyi-fastapi-backend/common/aspect/pre_auth.py new file mode 100644 index 0000000..b3c1856 --- /dev/null +++ b/ruoyi-fastapi-backend/common/aspect/pre_auth.py @@ -0,0 +1,146 @@ +import re +from typing import Literal, Optional, TypedDict, Union + +from fastapi import Depends, Request, params +from fastapi.security import OAuth2PasswordBearer +from sqlalchemy.ext.asyncio import AsyncSession + +from common.context import RequestContext +from config.env import AppConfig +from config.get_db import get_db +from exceptions.exception import AuthException +from module_admin.entity.vo.user_vo import CurrentUserModel +from module_admin.service.login_service import LoginService + + +# 定义排除路由的字典结构 +class ExcludeRoute(TypedDict, total=False): + """ + 排除路由的字典结构 + + :param path: 路由路径(必填) + :param methods: HTTP方法列表,空列表表示所有方法(可选,默认为[]) + :param ignore_paths: 需要忽略的特定路径列表,即使匹配通配符也不排除(可选,默认为[]) + """ + + path: str + methods: list[Literal['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']] + ignore_paths: list[str] + + +# 创建OAuth2PasswordBearer对象 +oauth2_scheme = OAuth2PasswordBearer(tokenUrl='/login') + + +class PreAuth: + """ + 登录认证前置校验依赖类 + """ + + def __init__(self, exclude_routes: Optional[list[ExcludeRoute]] = None) -> None: + """ + 初始化登录认证前置校验依赖 + + :param exclude_routes: 需要排除的路由列表,格式为: + [{'path': '/path1', 'methods': ['GET', 'POST']}, {'path': '/path2/{param}', 'methods': ['GET']}] + methods 可以是字符串或列表,空列表表示所有方法 + """ + self.exclude_routes = exclude_routes or [] + # 编译排除路径为正则表达式模式,并存储方法信息 + self.exclude_patterns = [] + + for route in self.exclude_routes: + # 使用TypedDict,确保路由字典包含path字段 + path = route.get('path', '') + methods = route.get('methods', []) + ignore_paths = route.get('ignore_paths', []) + + # 编译路径为正则表达式 + pattern = self._compile_path_pattern(path) + # 存储编译后的模式和方法信息 + self.exclude_patterns.append( + { + 'pattern': pattern, + 'methods': [method.upper() for method in methods], + 'original_path': path, + 'ignore_paths': ignore_paths, + } + ) + + def _compile_path_pattern(self, path: str) -> re.Pattern: + """ + 将FastAPI路径转换为正则表达式模式 + + :param path: FastAPI路径(如 /configKey/{config_key}) + :return: 编译后的正则表达式模式 + """ + # 将FastAPI路径参数转换为正则表达式 + # 例如:/configKey/{config_key} -> /configKey/[^/]+ + pattern_str = re.sub(r'\{[^}]+\}', r'[^/]+', path) + # 添加开始和结束锚点,确保精确匹配 + return re.compile(f'^{pattern_str}$') + + async def __call__(self, request: Request, db: AsyncSession = Depends(get_db)) -> Union[CurrentUserModel, None]: + """ + 执行登录认证校验 + + :param request: 当前请求对象 + :param db: 数据库会话 + :return: 当前用户信息 + """ + # 获取当前请求路径和方法 + path = request.url.path + method = request.method.upper() + + # 从配置中获取APP_ROOT_PATH + app_root_path = AppConfig.app_root_path + + # 去掉APP_ROOT_PATH前缀 + if app_root_path and path.startswith(app_root_path): + path = path[len(app_root_path) :] + + # 设置上下文变量 + RequestContext.set_current_exclude_patterns(self.exclude_patterns) + + # 检查路径和方法是否匹配排除模式 + for item in self.exclude_patterns: + pattern = item['pattern'] + exclude_methods = item['methods'] + ignore_paths = item['ignore_paths'] + + # 检查当前路径是否在忽略列表中 + if path in ignore_paths: + continue + + # 检查路径是否匹配,并且methods为空列表(匹配所有方法)或者当前方法在允许列表中 + if pattern.match(path) and (not exclude_methods or method in exclude_methods): + # 跳过认证 + return None + + # 否则执行正常认证 + token = request.headers.get('Authorization') + if not token: + raise AuthException(data='', message='用户未登录,请先完成登录') + current_user = await LoginService.get_current_user(request, token, db) + return current_user + + +def PreAuthDependency(exclude_routes: Optional[list[ExcludeRoute]] = None) -> params.Depends: # noqa: N802 + """ + 登录认证前置校验依赖 + + :param exclude_routes: 需要排除的路由列表,格式为: + [{'path': '/path1', 'methods': ['GET', 'POST']}, {'path': '/path2/{param}', 'methods': ['GET']}] + methods 可以是字符串或列表,空列表表示所有方法 + :return: 登录认证前置校验依赖 + """ + return Depends(PreAuth(exclude_routes)) + + +def CurrentUserDependency() -> params.Depends: # noqa: N802 + """ + 当前登录用户信息依赖 + + :return: 当前登录用户信息依赖 + """ + return Depends(LoginService.get_current_user) From d1fcb6dc112fab4567ec23ccf61f86ad1da368d7 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:56:48 +0800 Subject: [PATCH 05/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E9=A1=B9=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/dependency_util.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 ruoyi-fastapi-backend/utils/dependency_util.py diff --git a/ruoyi-fastapi-backend/utils/dependency_util.py b/ruoyi-fastapi-backend/utils/dependency_util.py new file mode 100644 index 0000000..23ace9d --- /dev/null +++ b/ruoyi-fastapi-backend/utils/dependency_util.py @@ -0,0 +1,49 @@ +from fastapi import Request + +from common.context import RequestContext +from config.env import AppConfig +from exceptions.exception import PermissionException + + +class DependencyUtil: + """ + 依赖项工具类 + """ + + @classmethod + def check_exclude_routes(cls, request: Request, err_msg: str = '当前路由不在认证规则内,不可使用该依赖项') -> None: + """ + 检查路径和方法是否匹配排除路由模式 + + :param request: 请求对象 + :param err_msg: 错误信息 + :return: None + """ + # 获取当前请求路径和方法 + path = request.url.path + method = request.method.upper() + + # 从配置中获取APP_ROOT_PATH + app_root_path = AppConfig.app_root_path + + # 去掉APP_ROOT_PATH前缀 + if app_root_path and path.startswith(app_root_path): + path = path[len(app_root_path) :] + + # 获取编译后的排除路由模式列表 + exclude_patterns = RequestContext.get_current_exclude_patterns() + + # 检查当前路由是否在排除路由列表中 + if path and method and exclude_patterns: + for item in exclude_patterns: + pattern = item['pattern'] + exclude_methods = item['methods'] + ignore_paths = item['ignore_paths'] + + # 检查当前路径是否在忽略列表中 + if path in ignore_paths: + continue + + # 检查路径是否匹配,并且methods为空列表(匹配所有方法)或者当前方法在允许列表中 + if pattern.match(path) and (not exclude_methods or method in exclude_methods): + raise PermissionException(data='', message=err_msg) From 077c8870b4854365027f12680682b706f3b093be Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:57:10 +0800 Subject: [PATCH 06/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EDataScopeDepend?= =?UTF-8?q?ency=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/aspect/data_scope.py | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/ruoyi-fastapi-backend/common/aspect/data_scope.py b/ruoyi-fastapi-backend/common/aspect/data_scope.py index fe52363..b4113f5 100644 --- a/ruoyi-fastapi-backend/common/aspect/data_scope.py +++ b/ruoyi-fastapi-backend/common/aspect/data_scope.py @@ -1,9 +1,9 @@ from typing import Optional -from fastapi import Depends +from fastapi import Depends, Request, params -from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService +from common.context import RequestContext +from utils.dependency_util import DependencyUtil class GetDataScope: @@ -37,7 +37,9 @@ class GetDataScope: self.user_alias = user_alias self.dept_alias = dept_alias - def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)) -> str: + def __call__(self, request: Request) -> str: + DependencyUtil.check_exclude_routes(request, err_msg='当前路由不在认证规则内,不可使用GetDataScope依赖项') + current_user = RequestContext.get_current_user() user_id = current_user.user.user_id dept_id = current_user.user.dept_id custom_data_scope_role_id_list = [ @@ -75,3 +77,21 @@ class GetDataScope: param_sql = f'or_({", ".join(param_sql_list)})' return param_sql + + +def DataScopeDependency( # noqa: N802 + query_alias: Optional[str] = '', + db_alias: Optional[str] = 'db', + user_alias: Optional[str] = 'user_id', + dept_alias: Optional[str] = 'dept_id', +) -> params.Depends: + """ + 当前用户数据权限依赖 + + :param query_alias: 所要查询表对应的sqlalchemy模型名称,默认为'' + :param db_alias: orm对象别名,默认为'db' + :param user_alias: 用户id字段别名,默认为'user_id' + :param dept_alias: 部门id字段别名,默认为'dept_id' + :return: 当前用户数据权限依赖 + """ + return Depends(GetDataScope(query_alias, db_alias, user_alias, dept_alias)) From 44678985e90f50d48e95fcfa52ef1842765d65eb Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:57:35 +0800 Subject: [PATCH 07/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EDBSessionDepend?= =?UTF-8?q?ency=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/common/aspect/db_seesion.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ruoyi-fastapi-backend/common/aspect/db_seesion.py diff --git a/ruoyi-fastapi-backend/common/aspect/db_seesion.py b/ruoyi-fastapi-backend/common/aspect/db_seesion.py new file mode 100644 index 0000000..3c88fb9 --- /dev/null +++ b/ruoyi-fastapi-backend/common/aspect/db_seesion.py @@ -0,0 +1,12 @@ +from fastapi import Depends, params + +from config.get_db import get_db + + +def DBSessionDependency() -> params.Depends: # noqa: N802 + """ + 数据库会话依赖 + + :return: 数据库会话依赖 + """ + return Depends(get_db) From 9a1c53d9f4107226d503ad344c30a80a3d6306c9 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:57:58 +0800 Subject: [PATCH 08/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EUserInterfaceAu?= =?UTF-8?q?thDependency=E5=92=8CRoleInterfaceAuthDependency=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/aspect/interface_auth.py | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/ruoyi-fastapi-backend/common/aspect/interface_auth.py b/ruoyi-fastapi-backend/common/aspect/interface_auth.py index db81952..f8f286d 100644 --- a/ruoyi-fastapi-backend/common/aspect/interface_auth.py +++ b/ruoyi-fastapi-backend/common/aspect/interface_auth.py @@ -1,10 +1,10 @@ from typing import Union -from fastapi import Depends +from fastapi import Depends, Request, params +from common.context import RequestContext from exceptions.exception import PermissionException -from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService +from utils.dependency_util import DependencyUtil class CheckUserInterfaceAuth: @@ -22,7 +22,11 @@ class CheckUserInterfaceAuth: self.perm = perm self.is_strict = is_strict - def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)) -> bool: + def __call__(self, request: Request) -> bool: + DependencyUtil.check_exclude_routes( + request, err_msg='当前路由不在认证规则内,不可使用CheckUserInterfaceAuth依赖项' + ) + current_user = RequestContext.get_current_user() user_auth_list = current_user.permissions if '*:*:*' in user_auth_list: return True @@ -52,7 +56,11 @@ class CheckRoleInterfaceAuth: self.role_key = role_key self.is_strict = is_strict - def __call__(self, current_user: CurrentUserModel = Depends(LoginService.get_current_user)) -> bool: + def __call__(self, request: Request) -> bool: + DependencyUtil.check_exclude_routes( + request, err_msg='当前路由不在认证规则内,不可使用CheckRoleInterfaceAuth依赖项' + ) + current_user = RequestContext.get_current_user() user_role_list = current_user.user.role user_role_key_list = [role.role_key for role in user_role_list] if isinstance(self.role_key, str) and self.role_key in user_role_key_list: @@ -64,3 +72,25 @@ class CheckRoleInterfaceAuth: elif any(role_key_str in user_role_key_list for role_key_str in self.role_key): return True raise PermissionException(data='', message='该用户无此接口权限') + + +def UserInterfaceAuthDependency(perm: Union[str, list], is_strict: bool = False) -> params.Depends: # noqa: N802 + """ + 根据权限标识校验当前用户接口权限依赖 + + :param perm: 权限标识 + :param is_strict: 当传入的权限标识是list类型时,是否开启严格模式,开启表示会校验列表中的每一个权限标识,所有的校验结果都需要为True才会通过 + :return: 根据权限标识校验当前用户接口权限依赖 + """ + return Depends(CheckUserInterfaceAuth(perm, is_strict)) + + +def RoleInterfaceAuthDependency(role_key: Union[str, list], is_strict: bool = False) -> params.Depends: # noqa: N802 + """ + 根据角色校验当前用户接口权限依赖 + + :param role_key: 角色标识 + :param is_strict: 当传入的角色标识是list类型时,是否开启严格模式,开启表示会校验列表中的每一个角色标识,所有的校验结果都需要为True才会通过 + :return: 根据角色校验当前用户接口权限依赖 + """ + return Depends(CheckRoleInterfaceAuth(role_key, is_strict)) From 184982eb08a13558ecd82750fadc2f45d7728d3d Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 16:59:18 +0800 Subject: [PATCH 09/49] =?UTF-8?q?perf:=20controller=E5=B1=82=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E4=BD=BF=E7=94=A8=E6=96=B0=E4=BE=9D=E8=B5=96=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/cache_controller.py | 29 +-- .../controller/common_controller.py | 6 +- .../controller/config_controller.py | 61 ++++--- .../controller/dept_controller.py | 67 ++++--- .../controller/dict_controller.py | 107 ++++++++---- .../module_admin/controller/job_controller.py | 97 ++++++---- .../module_admin/controller/log_controller.py | 67 ++++--- .../controller/login_controller.py | 17 +- .../controller/menu_controller.py | 57 +++--- .../controller/notice_controller.py | 47 +++-- .../controller/online_controller.py | 21 ++- .../controller/post_controller.py | 54 ++++-- .../controller/role_controller.py | 138 +++++++++------ .../controller/server_controller.py | 12 +- .../controller/user_controller.py | 165 +++++++++++------- .../controller/gen_controller.py | 91 ++++++---- .../templates/python/controller.py.jinja2 | 50 ++++-- 17 files changed, 687 insertions(+), 399 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index a5ff8ca..40b2684 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -1,19 +1,21 @@ from typing import Annotated -from fastapi import APIRouter, Depends, Path, Request, Response +from fastapi import APIRouter, Path, Request, Response -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import PreAuthDependency from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.service.cache_service import CacheService -from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil -cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[Depends(LoginService.get_current_user)]) +cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[PreAuthDependency()]) @cache_controller.get( - '', response_model=CacheMonitorModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))] + '', + response_model=CacheMonitorModel, + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_info(request: Request) -> Response: # 获取全量数据 @@ -26,7 +28,7 @@ async def get_monitor_cache_info(request: Request) -> Response: @cache_controller.get( '/getNames', response_model=list[CacheInfoModel], - dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))], + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_name(request: Request) -> Response: # 获取全量数据 @@ -39,7 +41,7 @@ async def get_monitor_cache_name(request: Request) -> Response: @cache_controller.get( '/getKeys/{cache_name}', response_model=list[str], - dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))], + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Path(description='缓存名称')]) -> Response: # 获取全量数据 @@ -52,7 +54,7 @@ async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Pat @cache_controller.get( '/getValue/{cache_name}/{cache_key}', response_model=CacheInfoModel, - dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))], + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_value( request: Request, @@ -67,7 +69,8 @@ async def get_monitor_cache_value( @cache_controller.delete( - '/clearCacheName/{cache_name}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))] + '/clearCacheName/{cache_name}', + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_name( request: Request, cache_name: Annotated[str, Path(description='缓存名称')] @@ -79,7 +82,8 @@ async def clear_monitor_cache_name( @cache_controller.delete( - '/clearCacheKey/{cache_key}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))] + '/clearCacheKey/{cache_key}', + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Path(description='缓存键')]) -> Response: clear_cache_key_result = await CacheService.clear_cache_monitor_cache_key_services(request, cache_key) @@ -88,7 +92,10 @@ async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Pa return ResponseUtil.success(msg=clear_cache_key_result.message) -@cache_controller.delete('/clearCacheAll', dependencies=[Depends(CheckUserInterfaceAuth('monitor:cache:list'))]) +@cache_controller.delete( + '/clearCacheAll', + dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], +) async def clear_monitor_cache_all(request: Request) -> Response: clear_cache_all_result = await CacheService.clear_cache_monitor_all_services(request) logger.info(clear_cache_all_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py index 714ecbd..9d37c8f 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py @@ -1,13 +1,13 @@ from typing import Annotated -from fastapi import APIRouter, BackgroundTasks, Depends, File, Query, Request, Response, UploadFile +from fastapi import APIRouter, BackgroundTasks, File, Query, Request, Response, UploadFile +from common.aspect.pre_auth import PreAuthDependency from module_admin.service.common_service import CommonService -from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil -common_controller = APIRouter(prefix='/common', dependencies=[Depends(LoginService.get_current_user)]) +common_controller = APIRouter(prefix='/common', dependencies=[PreAuthDependency()]) @common_controller.post('/upload') diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index ac8c811..e216269 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -1,33 +1,35 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.config_service import ConfigService -from module_admin.service.login_service import LoginService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -config_controller = APIRouter(prefix='/system/config', dependencies=[Depends(LoginService.get_current_user)]) +config_controller = APIRouter(prefix='/system/config', dependencies=[PreAuthDependency()]) @config_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:config:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:config:list')], ) async def get_system_config_list( request: Request, config_page_query: Annotated[ConfigPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 config_page_query_result = await ConfigService.get_config_list_services(query_db, config_page_query, is_page=True) @@ -36,14 +38,17 @@ async def get_system_config_list( return ResponseUtil.success(model_content=config_page_query_result) -@config_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:config:add'))]) +@config_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:config:add')], +) @ValidateFields(validate_model='add_config') @Log(title='参数管理', business_type=BusinessType.INSERT) async def add_system_config( request: Request, add_config: ConfigModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_config.create_by = current_user.user.user_name add_config.create_time = datetime.now() @@ -55,14 +60,17 @@ async def add_system_config( return ResponseUtil.success(msg=add_config_result.message) -@config_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:config:edit'))]) +@config_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:config:edit')], +) @ValidateFields(validate_model='edit_config') @Log(title='参数管理', business_type=BusinessType.UPDATE) async def edit_system_config( request: Request, edit_config: ConfigModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_config.update_by = current_user.user.user_name edit_config.update_time = datetime.now() @@ -72,11 +80,14 @@ async def edit_system_config( return ResponseUtil.success(msg=edit_config_result.message) -@config_controller.delete('/refreshCache', dependencies=[Depends(CheckUserInterfaceAuth('system:config:remove'))]) +@config_controller.delete( + '/refreshCache', + dependencies=[UserInterfaceAuthDependency('system:config:remove')], +) @Log(title='参数管理', business_type=BusinessType.UPDATE) async def refresh_system_config( request: Request, - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: refresh_config_result = await ConfigService.refresh_sys_config_services(request, query_db) logger.info(refresh_config_result.message) @@ -84,12 +95,15 @@ async def refresh_system_config( return ResponseUtil.success(msg=refresh_config_result.message) -@config_controller.delete('/{config_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:config:remove'))]) +@config_controller.delete( + '/{config_ids}', + dependencies=[UserInterfaceAuthDependency('system:config:remove')], +) @Log(title='参数管理', business_type=BusinessType.DELETE) async def delete_system_config( request: Request, config_ids: Annotated[str, Path(description='需要删除的参数主键')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_config = DeleteConfigModel(configIds=config_ids) delete_config_result = await ConfigService.delete_config_services(request, query_db, delete_config) @@ -99,12 +113,14 @@ async def delete_system_config( @config_controller.get( - '/{config_id}', response_model=ConfigModel, dependencies=[Depends(CheckUserInterfaceAuth('system:config:query'))] + '/{config_id}', + response_model=ConfigModel, + dependencies=[UserInterfaceAuthDependency('system:config:query')], ) async def query_detail_system_config( request: Request, config_id: Annotated[int, Path(description='参数主键')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: config_detail_result = await ConfigService.config_detail_services(query_db, config_id) logger.info(f'获取config_id为{config_id}的信息成功') @@ -121,12 +137,15 @@ async def query_system_config(request: Request, config_key: str) -> Response: return ResponseUtil.success(msg=config_query_result) -@config_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:config:export'))]) +@config_controller.post( + '/export', + dependencies=[UserInterfaceAuthDependency('system:config:export')], +) @Log(title='参数管理', business_type=BusinessType.EXPORT) async def export_system_config_list( request: Request, config_page_query: Annotated[ConfigPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 config_query_result = await ConfigService.get_config_list_services(query_db, config_page_query, is_page=False) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index a3a98e6..542e869 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -1,35 +1,35 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Path, Query, Request, Response +from fastapi import APIRouter, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.data_scope import GetDataScope -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.data_scope import DataScopeDependency +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.dept_service import DeptService -from module_admin.service.login_service import LoginService from utils.log_util import logger from utils.response_util import ResponseUtil -dept_controller = APIRouter(prefix='/system/dept', dependencies=[Depends(LoginService.get_current_user)]) +dept_controller = APIRouter(prefix='/system/dept', dependencies=[PreAuthDependency()]) @dept_controller.get( '/list/exclude/{dept_id}', response_model=list[DeptModel], - dependencies=[Depends(CheckUserInterfaceAuth('system:dept:list'))], + dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) async def get_system_dept_tree_for_edit_option( request: Request, dept_id: Annotated[int, Path(description='部门id')], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: dept_query = DeptModel(deptId=dept_id) dept_query_result = await DeptService.get_dept_for_edit_option_services(query_db, dept_query, data_scope_sql) @@ -39,13 +39,15 @@ async def get_system_dept_tree_for_edit_option( @dept_controller.get( - '/list', response_model=list[DeptModel], dependencies=[Depends(CheckUserInterfaceAuth('system:dept:list'))] + '/list', + response_model=list[DeptModel], + dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) async def get_system_dept_list( request: Request, dept_query: Annotated[DeptQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: dept_query_result = await DeptService.get_dept_list_services(query_db, dept_query, data_scope_sql) logger.info('获取成功') @@ -53,14 +55,17 @@ async def get_system_dept_list( return ResponseUtil.success(data=dept_query_result) -@dept_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:add'))]) +@dept_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:dept:add')], +) @ValidateFields(validate_model='add_dept') @Log(title='部门管理', business_type=BusinessType.INSERT) async def add_system_dept( request: Request, add_dept: DeptModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_dept.create_by = current_user.user.user_name add_dept.create_time = datetime.now() @@ -72,15 +77,18 @@ async def add_system_dept( return ResponseUtil.success(data=add_dept_result) -@dept_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:edit'))]) +@dept_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:dept:edit')], +) @ValidateFields(validate_model='edit_dept') @Log(title='部门管理', business_type=BusinessType.UPDATE) async def edit_system_dept( request: Request, edit_dept: DeptModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: if not current_user.user.admin: await DeptService.check_dept_data_scope_services(query_db, edit_dept.dept_id, data_scope_sql) @@ -92,14 +100,17 @@ async def edit_system_dept( return ResponseUtil.success(msg=edit_dept_result.message) -@dept_controller.delete('/{dept_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:dept:remove'))]) +@dept_controller.delete( + '/{dept_ids}', + dependencies=[UserInterfaceAuthDependency('system:dept:remove')], +) @Log(title='部门管理', business_type=BusinessType.DELETE) async def delete_system_dept( request: Request, dept_ids: Annotated[str, Path(description='需要删除的部门id')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: dept_id_list = dept_ids.split(',') if dept_ids else [] if dept_id_list: @@ -116,14 +127,16 @@ async def delete_system_dept( @dept_controller.get( - '/{dept_id}', response_model=DeptModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dept:query'))] + '/{dept_id}', + response_model=DeptModel, + dependencies=[UserInterfaceAuthDependency('system:dept:query')], ) async def query_detail_system_dept( request: Request, dept_id: Annotated[int, Path(description='部门id')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: if not current_user.user.admin: await DeptService.check_dept_data_scope_services(query_db, dept_id, data_scope_sql) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index 9a719ae..dd319d4 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -1,14 +1,15 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.dict_vo import ( DeleteDictDataModel, DeleteDictTypeModel, @@ -19,22 +20,23 @@ from module_admin.entity.vo.dict_vo import ( ) from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.dict_service import DictDataService, DictTypeService -from module_admin.service.login_service import LoginService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -dict_controller = APIRouter(prefix='/system/dict', dependencies=[Depends(LoginService.get_current_user)]) +dict_controller = APIRouter(prefix='/system/dict', dependencies=[PreAuthDependency()]) @dict_controller.get( - '/type/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:list'))] + '/type/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:dict:list')], ) async def get_system_dict_type_list( request: Request, dict_type_page_query: Annotated[DictTypePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 dict_type_page_query_result = await DictTypeService.get_dict_type_list_services( @@ -45,14 +47,17 @@ async def get_system_dict_type_list( return ResponseUtil.success(model_content=dict_type_page_query_result) -@dict_controller.post('/type', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:add'))]) +@dict_controller.post( + '/type', + dependencies=[UserInterfaceAuthDependency('system:dict:add')], +) @ValidateFields(validate_model='add_dict_type') @Log(title='字典类型', business_type=BusinessType.INSERT) async def add_system_dict_type( request: Request, add_dict_type: DictTypeModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_dict_type.create_by = current_user.user.user_name add_dict_type.create_time = datetime.now() @@ -64,14 +69,17 @@ async def add_system_dict_type( return ResponseUtil.success(msg=add_dict_type_result.message) -@dict_controller.put('/type', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:edit'))]) +@dict_controller.put( + '/type', + dependencies=[UserInterfaceAuthDependency('system:dict:edit')], +) @ValidateFields(validate_model='edit_dict_type') @Log(title='字典类型', business_type=BusinessType.UPDATE) async def edit_system_dict_type( request: Request, edit_dict_type: DictTypeModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_dict_type.update_by = current_user.user.user_name edit_dict_type.update_time = datetime.now() @@ -81,21 +89,27 @@ async def edit_system_dict_type( return ResponseUtil.success(msg=edit_dict_type_result.message) -@dict_controller.delete('/type/refreshCache', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) +@dict_controller.delete( + '/type/refreshCache', + dependencies=[UserInterfaceAuthDependency('system:dict:remove')], +) @Log(title='字典类型', business_type=BusinessType.UPDATE) -async def refresh_system_dict(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: +async def refresh_system_dict(request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()]) -> Response: refresh_dict_result = await DictTypeService.refresh_sys_dict_services(request, query_db) logger.info(refresh_dict_result.message) return ResponseUtil.success(msg=refresh_dict_result.message) -@dict_controller.delete('/type/{dict_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) +@dict_controller.delete( + '/type/{dict_ids}', + dependencies=[UserInterfaceAuthDependency('system:dict:remove')], +) @Log(title='字典类型', business_type=BusinessType.DELETE) async def delete_system_dict_type( request: Request, dict_ids: Annotated[str, Path(description='需要删除的字典主键')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_dict_type = DeleteDictTypeModel(dictIds=dict_ids) delete_dict_type_result = await DictTypeService.delete_dict_type_services(request, query_db, delete_dict_type) @@ -106,7 +120,7 @@ async def delete_system_dict_type( @dict_controller.get('/type/optionselect', response_model=list[DictTypeModel]) async def query_system_dict_type_options( - request: Request, query_db: Annotated[AsyncSession, Depends(get_db)] + request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()] ) -> Response: dict_type_query_result = await DictTypeService.get_dict_type_list_services( query_db, DictTypePageQueryModel(), is_page=False @@ -117,12 +131,14 @@ async def query_system_dict_type_options( @dict_controller.get( - '/type/{dict_id}', response_model=DictTypeModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:query'))] + '/type/{dict_id}', + response_model=DictTypeModel, + dependencies=[UserInterfaceAuthDependency('system:dict:query')], ) async def query_detail_system_dict_type( request: Request, dict_id: Annotated[int, Path(description='字典主键')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: dict_type_detail_result = await DictTypeService.dict_type_detail_services(query_db, dict_id) logger.info(f'获取dict_id为{dict_id}的信息成功') @@ -130,12 +146,15 @@ async def query_detail_system_dict_type( return ResponseUtil.success(data=dict_type_detail_result) -@dict_controller.post('/type/export', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:export'))]) +@dict_controller.post( + '/type/export', + dependencies=[UserInterfaceAuthDependency('system:dict:export')], +) @Log(title='字典类型', business_type=BusinessType.EXPORT) async def export_system_dict_type_list( request: Request, dict_type_page_query: Annotated[DictTypePageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 dict_type_query_result = await DictTypeService.get_dict_type_list_services( @@ -151,7 +170,7 @@ async def export_system_dict_type_list( async def query_system_dict_type_data( request: Request, dict_type: Annotated[str, Path(description='字典类型')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 dict_data_query_result = await DictDataService.query_dict_data_list_from_cache_services( @@ -163,12 +182,14 @@ async def query_system_dict_type_data( @dict_controller.get( - '/data/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:dict:list'))] + '/data/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:dict:list')], ) async def get_system_dict_data_list( request: Request, dict_data_page_query: Annotated[DictDataPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 dict_data_page_query_result = await DictDataService.get_dict_data_list_services( @@ -179,14 +200,17 @@ async def get_system_dict_data_list( return ResponseUtil.success(model_content=dict_data_page_query_result) -@dict_controller.post('/data', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:add'))]) +@dict_controller.post( + '/data', + dependencies=[UserInterfaceAuthDependency('system:dict:add')], +) @ValidateFields(validate_model='add_dict_data') @Log(title='字典数据', business_type=BusinessType.INSERT) async def add_system_dict_data( request: Request, add_dict_data: DictDataModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_dict_data.create_by = current_user.user.user_name add_dict_data.create_time = datetime.now() @@ -198,14 +222,17 @@ async def add_system_dict_data( return ResponseUtil.success(msg=add_dict_data_result.message) -@dict_controller.put('/data', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:edit'))]) +@dict_controller.put( + '/data', + dependencies=[UserInterfaceAuthDependency('system:dict:edit')], +) @ValidateFields(validate_model='edit_dict_data') @Log(title='字典数据', business_type=BusinessType.UPDATE) async def edit_system_dict_data( request: Request, edit_dict_data: DictDataModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_dict_data.update_by = current_user.user.user_name edit_dict_data.update_time = datetime.now() @@ -215,12 +242,15 @@ async def edit_system_dict_data( return ResponseUtil.success(msg=edit_dict_data_result.message) -@dict_controller.delete('/data/{dict_codes}', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:remove'))]) +@dict_controller.delete( + '/data/{dict_codes}', + dependencies=[UserInterfaceAuthDependency('system:dict:remove')], +) @Log(title='字典数据', business_type=BusinessType.DELETE) async def delete_system_dict_data( request: Request, dict_codes: Annotated[str, Path(description='需要删除的字典编码')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_dict_data = DeleteDictDataModel(dictCodes=dict_codes) delete_dict_data_result = await DictDataService.delete_dict_data_services(request, query_db, delete_dict_data) @@ -232,12 +262,12 @@ async def delete_system_dict_data( @dict_controller.get( '/data/{dict_code}', response_model=DictDataModel, - dependencies=[Depends(CheckUserInterfaceAuth('system:dict:query'))], + dependencies=[UserInterfaceAuthDependency('system:dict:query')], ) async def query_detail_system_dict_data( request: Request, dict_code: Annotated[int, Path(description='字典编码')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: detail_dict_data_result = await DictDataService.dict_data_detail_services(query_db, dict_code) logger.info(f'获取dict_code为{dict_code}的信息成功') @@ -245,12 +275,15 @@ async def query_detail_system_dict_data( return ResponseUtil.success(data=detail_dict_data_result) -@dict_controller.post('/data/export', dependencies=[Depends(CheckUserInterfaceAuth('system:dict:export'))]) +@dict_controller.post( + '/data/export', + dependencies=[UserInterfaceAuthDependency('system:dict:export')], +) @Log(title='字典数据', business_type=BusinessType.EXPORT) async def export_system_dict_data_list( request: Request, dict_data_page_query: Annotated[DictDataPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 dict_data_query_result = await DictDataService.get_dict_data_list_services( diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index efe9021..5d656be 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -1,14 +1,15 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.job_vo import ( DeleteJobLogModel, DeleteJobModel, @@ -20,22 +21,23 @@ from module_admin.entity.vo.job_vo import ( from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.job_log_service import JobLogService from module_admin.service.job_service import JobService -from module_admin.service.login_service import LoginService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -job_controller = APIRouter(prefix='/monitor', dependencies=[Depends(LoginService.get_current_user)]) +job_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()]) @job_controller.get( - '/job/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:list'))] + '/job/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('monitor:job:list')], ) async def get_system_job_list( request: Request, job_page_query: Annotated[JobPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 notice_page_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=True) @@ -44,14 +46,17 @@ async def get_system_job_list( return ResponseUtil.success(model_content=notice_page_query_result) -@job_controller.post('/job', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:add'))]) +@job_controller.post( + '/job', + dependencies=[UserInterfaceAuthDependency('monitor:job:add')], +) @ValidateFields(validate_model='add_job') @Log(title='定时任务', business_type=BusinessType.INSERT) async def add_system_job( request: Request, add_job: JobModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_job.create_by = current_user.user.user_name add_job.create_time = datetime.now() @@ -63,14 +68,17 @@ async def add_system_job( return ResponseUtil.success(msg=add_job_result.message) -@job_controller.put('/job', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:edit'))]) +@job_controller.put( + '/job', + dependencies=[UserInterfaceAuthDependency('monitor:job:edit')], +) @ValidateFields(validate_model='edit_job') @Log(title='定时任务', business_type=BusinessType.UPDATE) async def edit_system_job( request: Request, edit_job: EditJobModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_job.update_by = current_user.user.user_name edit_job.update_time = datetime.now() @@ -80,13 +88,16 @@ async def edit_system_job( return ResponseUtil.success(msg=edit_job_result.message) -@job_controller.put('/job/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:changeStatus'))]) +@job_controller.put( + '/job/changeStatus', + dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')], +) @Log(title='定时任务', business_type=BusinessType.UPDATE) async def change_system_job_status( request: Request, change_job: EditJobModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_job = EditJobModel( jobId=change_job.job_id, @@ -101,12 +112,15 @@ async def change_system_job_status( return ResponseUtil.success(msg=edit_job_result.message) -@job_controller.put('/job/run', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:changeStatus'))]) +@job_controller.put( + '/job/run', + dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')], +) @Log(title='定时任务', business_type=BusinessType.UPDATE) async def execute_system_job( request: Request, execute_job: JobModel, - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: execute_job_result = await JobService.execute_job_once_services(query_db, execute_job) logger.info(execute_job_result.message) @@ -114,12 +128,15 @@ async def execute_system_job( return ResponseUtil.success(msg=execute_job_result.message) -@job_controller.delete('/job/{job_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) +@job_controller.delete( + '/job/{job_ids}', + dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], +) @Log(title='定时任务', business_type=BusinessType.DELETE) async def delete_system_job( request: Request, job_ids: Annotated[str, Path(description='需要删除的定时任务ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_job = DeleteJobModel(jobIds=job_ids) delete_job_result = await JobService.delete_job_services(query_db, delete_job) @@ -129,12 +146,14 @@ async def delete_system_job( @job_controller.get( - '/job/{job_id}', response_model=JobModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:query'))] + '/job/{job_id}', + response_model=JobModel, + dependencies=[UserInterfaceAuthDependency('monitor:job:query')], ) async def query_detail_system_job( request: Request, job_id: Annotated[int, Path(description='任务ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: job_detail_result = await JobService.job_detail_services(query_db, job_id) logger.info(f'获取job_id为{job_id}的信息成功') @@ -142,12 +161,15 @@ async def query_detail_system_job( return ResponseUtil.success(data=job_detail_result) -@job_controller.post('/job/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:export'))]) +@job_controller.post( + '/job/export', + dependencies=[UserInterfaceAuthDependency('monitor:job:export')], +) @Log(title='定时任务', business_type=BusinessType.EXPORT) async def export_system_job_list( request: Request, job_page_query: Annotated[JobPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 job_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=False) @@ -158,12 +180,14 @@ async def export_system_job_list( @job_controller.get( - '/jobLog/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:list'))] + '/jobLog/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('monitor:job:list')], ) async def get_system_job_log_list( request: Request, job_log_page_query: Annotated[JobLogPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 job_log_page_query_result = await JobLogService.get_job_log_list_services( @@ -174,11 +198,14 @@ async def get_system_job_log_list( return ResponseUtil.success(model_content=job_log_page_query_result) -@job_controller.delete('/jobLog/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) +@job_controller.delete( + '/jobLog/clean', + dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], +) @Log(title='定时任务调度日志', business_type=BusinessType.CLEAN) async def clear_system_job_log( request: Request, - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: clear_job_log_result = await JobLogService.clear_job_log_services(query_db) logger.info(clear_job_log_result.message) @@ -186,12 +213,15 @@ async def clear_system_job_log( return ResponseUtil.success(msg=clear_job_log_result.message) -@job_controller.delete('/jobLog/{job_log_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:remove'))]) +@job_controller.delete( + '/jobLog/{job_log_ids}', + dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], +) @Log(title='定时任务调度日志', business_type=BusinessType.DELETE) async def delete_system_job_log( request: Request, job_log_ids: Annotated[str, Path(description='需要删除的定时任务日志ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_job_log = DeleteJobLogModel(jobLogIds=job_log_ids) delete_job_log_result = await JobLogService.delete_job_log_services(query_db, delete_job_log) @@ -200,12 +230,15 @@ async def delete_system_job_log( return ResponseUtil.success(msg=delete_job_log_result.message) -@job_controller.post('/jobLog/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:job:export'))]) +@job_controller.post( + '/jobLog/export', + dependencies=[UserInterfaceAuthDependency('monitor:job:export')], +) @Log(title='定时任务调度日志', business_type=BusinessType.EXPORT) async def export_system_job_log_list( request: Request, job_log_page_query: Annotated[JobLogPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 job_log_query_result = await JobLogService.get_job_log_list_services(query_db, job_log_page_query, is_page=False) diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index c64943e..c9238a2 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -1,12 +1,13 @@ from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.log_vo import ( DeleteLoginLogModel, DeleteOperLogModel, @@ -15,24 +16,23 @@ from module_admin.entity.vo.log_vo import ( UnlockUser, ) from module_admin.service.log_service import LoginLogService, OperationLogService -from module_admin.service.login_service import LoginService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -log_controller = APIRouter(prefix='/monitor', dependencies=[Depends(LoginService.get_current_user)]) +log_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()]) @log_controller.get( '/operlog/list', response_model=PageResponseModel, - dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:list'))], + dependencies=[UserInterfaceAuthDependency('monitor:operlog:list')], ) async def get_system_operation_log_list( request: Request, operation_log_page_query: Annotated[OperLogPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 operation_log_page_query_result = await OperationLogService.get_operation_log_list_services( @@ -43,21 +43,29 @@ async def get_system_operation_log_list( return ResponseUtil.success(model_content=operation_log_page_query_result) -@log_controller.delete('/operlog/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:remove'))]) +@log_controller.delete( + '/operlog/clean', + dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')], +) @Log(title='操作日志', business_type=BusinessType.CLEAN) -async def clear_system_operation_log(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: +async def clear_system_operation_log( + request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()] +) -> Response: clear_operation_log_result = await OperationLogService.clear_operation_log_services(query_db) logger.info(clear_operation_log_result.message) return ResponseUtil.success(msg=clear_operation_log_result.message) -@log_controller.delete('/operlog/{oper_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:remove'))]) +@log_controller.delete( + '/operlog/{oper_ids}', + dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')], +) @Log(title='操作日志', business_type=BusinessType.DELETE) async def delete_system_operation_log( request: Request, oper_ids: Annotated[str, Path(description='需要删除的日志主键')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_operation_log = DeleteOperLogModel(operIds=oper_ids) delete_operation_log_result = await OperationLogService.delete_operation_log_services( @@ -68,12 +76,15 @@ async def delete_system_operation_log( return ResponseUtil.success(msg=delete_operation_log_result.message) -@log_controller.post('/operlog/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:operlog:export'))]) +@log_controller.post( + '/operlog/export', + dependencies=[UserInterfaceAuthDependency('monitor:operlog:export')], +) @Log(title='操作日志', business_type=BusinessType.EXPORT) async def export_system_operation_log_list( request: Request, operation_log_page_query: Annotated[OperLogPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 operation_log_query_result = await OperationLogService.get_operation_log_list_services( @@ -90,12 +101,12 @@ async def export_system_operation_log_list( @log_controller.get( '/logininfor/list', response_model=PageResponseModel, - dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:list'))], + dependencies=[UserInterfaceAuthDependency('monitor:logininfor:list')], ) async def get_system_login_log_list( request: Request, login_log_page_query: Annotated[LoginLogPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 login_log_page_query_result = await LoginLogService.get_login_log_list_services( @@ -106,9 +117,14 @@ async def get_system_login_log_list( return ResponseUtil.success(model_content=login_log_page_query_result) -@log_controller.delete('/logininfor/clean', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:remove'))]) +@log_controller.delete( + '/logininfor/clean', + dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')], +) @Log(title='登录日志', business_type=BusinessType.CLEAN) -async def clear_system_login_log(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: +async def clear_system_login_log( + request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()] +) -> Response: clear_login_log_result = await LoginLogService.clear_login_log_services(query_db) logger.info(clear_login_log_result.message) @@ -116,13 +132,14 @@ async def clear_system_login_log(request: Request, query_db: Annotated[AsyncSess @log_controller.delete( - '/logininfor/{info_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:remove'))] + '/logininfor/{info_ids}', + dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')], ) @Log(title='登录日志', business_type=BusinessType.DELETE) async def delete_system_login_log( request: Request, info_ids: Annotated[str, Path(description='需要删除的访问ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_login_log = DeleteLoginLogModel(infoIds=info_ids) delete_login_log_result = await LoginLogService.delete_login_log_services(query_db, delete_login_log) @@ -132,13 +149,14 @@ async def delete_system_login_log( @log_controller.get( - '/logininfor/unlock/{user_name}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:unlock'))] + '/logininfor/unlock/{user_name}', + dependencies=[UserInterfaceAuthDependency('monitor:logininfor:unlock')], ) @Log(title='账户解锁', business_type=BusinessType.OTHER) async def unlock_system_user( request: Request, user_name: Annotated[str, Path(description='用户名称')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: unlock_user = UnlockUser(userName=user_name) unlock_user_result = await LoginLogService.unlock_user_services(request, unlock_user) @@ -147,12 +165,15 @@ async def unlock_system_user( return ResponseUtil.success(msg=unlock_user_result.message) -@log_controller.post('/logininfor/export', dependencies=[Depends(CheckUserInterfaceAuth('monitor:logininfor:export'))]) +@log_controller.post( + '/logininfor/export', + dependencies=[UserInterfaceAuthDependency('monitor:logininfor:export')], +) @Log(title='登录日志', business_type=BusinessType.EXPORT) async def export_system_login_log_list( request: Request, login_log_page_query: Annotated[LoginLogPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 login_log_query_result = await LoginLogService.get_login_log_list_services( diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 6df7872..b00b3e1 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -7,9 +7,10 @@ from fastapi import APIRouter, Depends, Request, Response from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.pre_auth import CurrentUserDependency from common.enums import BusinessType, RedisInitKeyConfig from config.env import AppConfig, JwtConfig -from config.get_db import get_db from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.login_vo import Token, UserLogin, UserRegister from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel @@ -26,7 +27,7 @@ login_controller = APIRouter() async def login( request: Request, form_data: Annotated[CustomOAuth2PasswordRequestForm, Depends()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: captcha_enabled = ( await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true' @@ -79,7 +80,7 @@ async def login( @login_controller.get('/getInfo', response_model=CurrentUserModel) async def get_login_user_info( - request: Request, current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)] + request: Request, current_user: Annotated[CurrentUserModel, CurrentUserDependency()] ) -> Response: logger.info('获取成功') @@ -89,8 +90,8 @@ async def get_login_user_info( @login_controller.get('/getRouters') async def get_login_user_routers( request: Request, - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - query_db: Annotated[AsyncSession, Depends(get_db)], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: logger.info('获取成功') user_routers = await LoginService.get_current_user_routers(current_user.user.user_id, query_db) @@ -102,7 +103,7 @@ async def get_login_user_routers( async def register_user( request: Request, user_register: UserRegister, - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: user_register_result = await LoginService.register_user_services(request, query_db, user_register) logger.info(user_register_result.message) @@ -111,7 +112,7 @@ async def register_user( # @login_controller.post("/getSmsCode", response_model=SmsCode) -# async def get_sms_code(request: Request, user: ResetUserModel, query_db: AsyncSession = Depends(get_db)): +# async def get_sms_code(request: Request, user: ResetUserModel, query_db: AsyncSession = DBSessionDependency()): # try: # sms_result = await LoginService.get_sms_code_services(request, query_db, user) # if sms_result.is_success: @@ -126,7 +127,7 @@ async def register_user( # # # @login_controller.post("/forgetPwd", response_model=CrudResponseModel) -# async def forget_user_pwd(request: Request, forget_user: ResetUserModel, query_db: AsyncSession = Depends(get_db)): +# async def forget_user_pwd(request: Request, forget_user: ResetUserModel, query_db: AsyncSession = DBSessionDependency()): # try: # forget_user_result = await LoginService.forget_user_services(request, query_db, forget_user) # if forget_user_result.is_success: diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index 0359ab0..fd157d1 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -1,29 +1,29 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Path, Query, Request, Response +from fastapi import APIRouter, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService from module_admin.service.menu_service import MenuService from utils.log_util import logger from utils.response_util import ResponseUtil -menu_controller = APIRouter(prefix='/system/menu', dependencies=[Depends(LoginService.get_current_user)]) +menu_controller = APIRouter(prefix='/system/menu', dependencies=[PreAuthDependency()]) @menu_controller.get('/treeselect') async def get_system_menu_tree( request: Request, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: menu_query_result = await MenuService.get_menu_tree_services(query_db, current_user) logger.info('获取成功') @@ -35,8 +35,8 @@ async def get_system_menu_tree( async def get_system_role_menu_tree( request: Request, role_id: Annotated[int, Path(description='角色ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: role_menu_query_result = await MenuService.get_role_menu_tree_services(query_db, role_id, current_user) logger.info('获取成功') @@ -45,13 +45,15 @@ async def get_system_role_menu_tree( @menu_controller.get( - '/list', response_model=list[MenuModel], dependencies=[Depends(CheckUserInterfaceAuth('system:menu:list'))] + '/list', + response_model=list[MenuModel], + dependencies=[UserInterfaceAuthDependency('system:menu:list')], ) async def get_system_menu_list( request: Request, menu_query: Annotated[MenuQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: menu_query_result = await MenuService.get_menu_list_services(query_db, menu_query, current_user) logger.info('获取成功') @@ -59,14 +61,17 @@ async def get_system_menu_list( return ResponseUtil.success(data=menu_query_result) -@menu_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:add'))]) +@menu_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:menu:add')], +) @ValidateFields(validate_model='add_menu') @Log(title='菜单管理', business_type=BusinessType.INSERT) async def add_system_menu( request: Request, add_menu: MenuModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_menu.create_by = current_user.user.user_name add_menu.create_time = datetime.now() @@ -78,14 +83,17 @@ async def add_system_menu( return ResponseUtil.success(msg=add_menu_result.message) -@menu_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:edit'))]) +@menu_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:menu:edit')], +) @ValidateFields(validate_model='edit_menu') @Log(title='菜单管理', business_type=BusinessType.UPDATE) async def edit_system_menu( request: Request, edit_menu: MenuModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_menu.update_by = current_user.user.user_name edit_menu.update_time = datetime.now() @@ -95,12 +103,15 @@ async def edit_system_menu( return ResponseUtil.success(msg=edit_menu_result.message) -@menu_controller.delete('/{menu_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:menu:remove'))]) +@menu_controller.delete( + '/{menu_ids}', + dependencies=[UserInterfaceAuthDependency('system:menu:remove')], +) @Log(title='菜单管理', business_type=BusinessType.DELETE) async def delete_system_menu( request: Request, menu_ids: Annotated[str, Path(description='需要删除的菜单ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_menu = DeleteMenuModel(menuIds=menu_ids) delete_menu_result = await MenuService.delete_menu_services(query_db, delete_menu) @@ -110,12 +121,14 @@ async def delete_system_menu( @menu_controller.get( - '/{menu_id}', response_model=MenuModel, dependencies=[Depends(CheckUserInterfaceAuth('system:menu:query'))] + '/{menu_id}', + response_model=MenuModel, + dependencies=[UserInterfaceAuthDependency('system:menu:query')], ) async def query_detail_system_menu( request: Request, menu_id: Annotated[int, Path(description='菜单ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: menu_detail_result = await MenuService.menu_detail_services(query_db, menu_id) logger.info(f'获取menu_id为{menu_id}的信息成功') diff --git a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py index 8dcb2cf..e4987d2 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py @@ -1,32 +1,34 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Path, Query, Request, Response +from fastapi import APIRouter, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService from module_admin.service.notice_service import NoticeService from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -notice_controller = APIRouter(prefix='/system/notice', dependencies=[Depends(LoginService.get_current_user)]) +notice_controller = APIRouter(prefix='/system/notice', dependencies=[PreAuthDependency()]) @notice_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:notice:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:notice:list')], ) async def get_system_notice_list( request: Request, notice_page_query: Annotated[NoticePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 notice_page_query_result = await NoticeService.get_notice_list_services(query_db, notice_page_query, is_page=True) @@ -35,14 +37,17 @@ async def get_system_notice_list( return ResponseUtil.success(model_content=notice_page_query_result) -@notice_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:add'))]) +@notice_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:notice:add')], +) @ValidateFields(validate_model='add_notice') @Log(title='通知公告', business_type=BusinessType.INSERT) async def add_system_notice( request: Request, add_notice: NoticeModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_notice.create_by = current_user.user.user_name add_notice.create_time = datetime.now() @@ -54,14 +59,17 @@ async def add_system_notice( return ResponseUtil.success(msg=add_notice_result.message) -@notice_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:edit'))]) +@notice_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:notice:edit')], +) @ValidateFields(validate_model='edit_notice') @Log(title='通知公告', business_type=BusinessType.UPDATE) async def edit_system_notice( request: Request, edit_notice: NoticeModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_notice.update_by = current_user.user.user_name edit_notice.update_time = datetime.now() @@ -71,12 +79,15 @@ async def edit_system_notice( return ResponseUtil.success(msg=edit_notice_result.message) -@notice_controller.delete('/{notice_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:notice:remove'))]) +@notice_controller.delete( + '/{notice_ids}', + dependencies=[UserInterfaceAuthDependency('system:notice:remove')], +) @Log(title='通知公告', business_type=BusinessType.DELETE) async def delete_system_notice( request: Request, notice_ids: Annotated[str, Path(description='需要删除的公告ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_notice = DeleteNoticeModel(noticeIds=notice_ids) delete_notice_result = await NoticeService.delete_notice_services(query_db, delete_notice) @@ -86,12 +97,14 @@ async def delete_system_notice( @notice_controller.get( - '/{notice_id}', response_model=NoticeModel, dependencies=[Depends(CheckUserInterfaceAuth('system:notice:query'))] + '/{notice_id}', + response_model=NoticeModel, + dependencies=[UserInterfaceAuthDependency('system:notice:query')], ) async def query_detail_system_post( request: Request, notice_id: Annotated[int, Path(description='公告ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: notice_detail_result = await NoticeService.notice_detail_services(query_db, notice_id) logger.info(f'获取notice_id为{notice_id}的信息成功') diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index 4fde252..b84f1bf 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -1,24 +1,26 @@ from typing import Annotated -from fastapi import APIRouter, Depends, Path, Query, Request, Response +from fastapi import APIRouter, Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineQueryModel -from module_admin.service.login_service import LoginService from module_admin.service.online_service import OnlineService from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -online_controller = APIRouter(prefix='/monitor/online', dependencies=[Depends(LoginService.get_current_user)]) +online_controller = APIRouter(prefix='/monitor/online', dependencies=[PreAuthDependency()]) @online_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:online:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('monitor:online:list')], ) async def get_monitor_online_list( request: Request, @@ -33,12 +35,15 @@ async def get_monitor_online_list( ) -@online_controller.delete('/{token_ids}', dependencies=[Depends(CheckUserInterfaceAuth('monitor:online:forceLogout'))]) +@online_controller.delete( + '/{token_ids}', + dependencies=[UserInterfaceAuthDependency('monitor:online:forceLogout')], +) @Log(title='在线用户', business_type=BusinessType.FORCE) async def delete_monitor_online( request: Request, token_ids: Annotated[str, Path(description='需要强退的会话编号')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_online = DeleteOnlineModel(tokenIds=token_ids) delete_online_result = await OnlineService.delete_online_services(request, delete_online) diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index 64368ae..c03f40b 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -1,33 +1,35 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService from module_admin.service.post_service import PostService from utils.common_util import bytes2file_response from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -post_controller = APIRouter(prefix='/system/post', dependencies=[Depends(LoginService.get_current_user)]) +post_controller = APIRouter(prefix='/system/post', dependencies=[PreAuthDependency()]) @post_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:post:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:post:list')], ) async def get_system_post_list( request: Request, post_page_query: Annotated[PostPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 post_page_query_result = await PostService.get_post_list_services(query_db, post_page_query, is_page=True) @@ -36,14 +38,17 @@ async def get_system_post_list( return ResponseUtil.success(model_content=post_page_query_result) -@post_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:post:add'))]) +@post_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:post:add')], +) @ValidateFields(validate_model='add_post') @Log(title='岗位管理', business_type=BusinessType.INSERT) async def add_system_post( request: Request, add_post: PostModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_post.create_by = current_user.user.user_name add_post.create_time = datetime.now() @@ -55,14 +60,17 @@ async def add_system_post( return ResponseUtil.success(msg=add_post_result.message) -@post_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:post:edit'))]) +@post_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:post:edit')], +) @ValidateFields(validate_model='edit_post') @Log(title='岗位管理', business_type=BusinessType.UPDATE) async def edit_system_post( request: Request, edit_post: PostModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_post.update_by = current_user.user.user_name edit_post.update_time = datetime.now() @@ -72,12 +80,15 @@ async def edit_system_post( return ResponseUtil.success(msg=edit_post_result.message) -@post_controller.delete('/{post_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:post:remove'))]) +@post_controller.delete( + '/{post_ids}', + dependencies=[UserInterfaceAuthDependency('system:post:remove')], +) @Log(title='岗位管理', business_type=BusinessType.DELETE) async def delete_system_post( request: Request, post_ids: Annotated[str, Path(description='需要删除的岗位ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_post = DeletePostModel(postIds=post_ids) delete_post_result = await PostService.delete_post_services(query_db, delete_post) @@ -87,12 +98,14 @@ async def delete_system_post( @post_controller.get( - '/{post_id}', response_model=PostModel, dependencies=[Depends(CheckUserInterfaceAuth('system:post:query'))] + '/{post_id}', + response_model=PostModel, + dependencies=[UserInterfaceAuthDependency('system:post:query')], ) async def query_detail_system_post( request: Request, post_id: Annotated[int, Path(description='岗位ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: post_detail_result = await PostService.post_detail_services(query_db, post_id) logger.info(f'获取post_id为{post_id}的信息成功') @@ -100,12 +113,15 @@ async def query_detail_system_post( return ResponseUtil.success(data=post_detail_result) -@post_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:post:export'))]) +@post_controller.post( + '/export', + dependencies=[UserInterfaceAuthDependency('system:post:export')], +) @Log(title='岗位管理', business_type=BusinessType.EXPORT) async def export_system_post_list( request: Request, post_page_query: Annotated[PostPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 post_query_result = await PostService.get_post_list_services(query_db, post_page_query, is_page=False) diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index c13bf55..e5fe7a2 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -1,20 +1,20 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.data_scope import GetDataScope -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.data_scope import DataScopeDependency +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.role_vo import AddRoleModel, DeleteRoleModel, RoleModel, RolePageQueryModel from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserRolePageQueryModel from module_admin.service.dept_service import DeptService -from module_admin.service.login_service import LoginService from module_admin.service.role_service import RoleService from module_admin.service.user_service import UserService from utils.common_util import bytes2file_response @@ -22,15 +22,18 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -role_controller = APIRouter(prefix='/system/role', dependencies=[Depends(LoginService.get_current_user)]) +role_controller = APIRouter(prefix='/system/role', dependencies=[PreAuthDependency()]) -@role_controller.get('/deptTree/{role_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))]) +@role_controller.get( + '/deptTree/{role_id}', + dependencies=[UserInterfaceAuthDependency('system:role:query')], +) async def get_system_role_dept_tree( request: Request, role_id: Annotated[int, Path(description='角色ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql) role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id) @@ -41,13 +44,15 @@ async def get_system_role_dept_tree( @role_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_role_list( request: Request, role_page_query: Annotated[RolePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: role_page_query_result = await RoleService.get_role_list_services( query_db, role_page_query, data_scope_sql, is_page=True @@ -57,14 +62,17 @@ async def get_system_role_list( return ResponseUtil.success(model_content=role_page_query_result) -@role_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:role:add'))]) +@role_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:role:add')], +) @ValidateFields(validate_model='add_role') @Log(title='角色管理', business_type=BusinessType.INSERT) async def add_system_role( request: Request, add_role: AddRoleModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: add_role.create_by = current_user.user.user_name add_role.create_time = datetime.now() @@ -76,15 +84,18 @@ async def add_system_role( return ResponseUtil.success(msg=add_role_result.message) -@role_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:role:edit')], +) @ValidateFields(validate_model='edit_role') @Log(title='角色管理', business_type=BusinessType.UPDATE) async def edit_system_role( request: Request, edit_role: AddRoleModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: await RoleService.check_role_allowed_services(edit_role) if not current_user.user.admin: @@ -97,14 +108,17 @@ async def edit_system_role( return ResponseUtil.success(msg=edit_role_result.message) -@role_controller.put('/dataScope', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put( + '/dataScope', + dependencies=[UserInterfaceAuthDependency('system:role:edit')], +) @Log(title='角色管理', business_type=BusinessType.GRANT) async def edit_system_role_datascope( request: Request, role_data_scope: AddRoleModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: await RoleService.check_role_allowed_services(role_data_scope) if not current_user.user.admin: @@ -123,14 +137,17 @@ async def edit_system_role_datascope( return ResponseUtil.success(msg=role_data_scope_result.message) -@role_controller.delete('/{role_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:role:remove'))]) +@role_controller.delete( + '/{role_ids}', + dependencies=[UserInterfaceAuthDependency('system:role:remove')], +) @Log(title='角色管理', business_type=BusinessType.DELETE) async def delete_system_role( request: Request, role_ids: Annotated[str, Path(description='需要删除的角色ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: role_id_list = role_ids.split(',') if role_ids else [] if role_id_list: @@ -146,14 +163,16 @@ async def delete_system_role( @role_controller.get( - '/{role_id}', response_model=RoleModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:query'))] + '/{role_id}', + response_model=RoleModel, + dependencies=[UserInterfaceAuthDependency('system:role:query')], ) async def query_detail_system_role( request: Request, role_id: Annotated[int, Path(description='角色ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(role_id), data_scope_sql) @@ -163,13 +182,16 @@ async def query_detail_system_role( return ResponseUtil.success(data=role_detail_result.model_dump(by_alias=True)) -@role_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:role:export'))]) +@role_controller.post( + '/export', + dependencies=[UserInterfaceAuthDependency('system:role:export')], +) @Log(title='角色管理', business_type=BusinessType.EXPORT) async def export_system_role_list( request: Request, role_page_query: Annotated[RolePageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: # 获取全量数据 role_query_result = await RoleService.get_role_list_services( @@ -181,14 +203,17 @@ async def export_system_role_list( return ResponseUtil.streaming(data=bytes2file_response(role_export_result)) -@role_controller.put('/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put( + '/changeStatus', + dependencies=[UserInterfaceAuthDependency('system:role:edit')], +) @Log(title='角色管理', business_type=BusinessType.UPDATE) async def reset_system_role_status( request: Request, change_role: AddRoleModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: await RoleService.check_role_allowed_services(change_role) if not current_user.user.admin: @@ -209,13 +234,13 @@ async def reset_system_role_status( @role_controller.get( '/authUser/allocatedList', response_model=PageResponseModel, - dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))], + dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_allocated_user_list( request: Request, user_role: Annotated[UserRolePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services( query_db, user_role, data_scope_sql, is_page=True @@ -228,13 +253,13 @@ async def get_system_allocated_user_list( @role_controller.get( '/authUser/unallocatedList', response_model=PageResponseModel, - dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))], + dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_unallocated_user_list( request: Request, user_role: Annotated[UserRolePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services( query_db, user_role, data_scope_sql, is_page=True @@ -244,14 +269,17 @@ async def get_system_unallocated_user_list( return ResponseUtil.success(model_content=role_user_unallocated_page_query_result) -@role_controller.put('/authUser/selectAll', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put( + '/authUser/selectAll', + dependencies=[UserInterfaceAuthDependency('system:role:edit')], +) @Log(title='角色管理', business_type=BusinessType.GRANT) async def add_system_role_user( request: Request, add_role_user: Annotated[CrudUserRoleModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: if not current_user.user.admin: await RoleService.check_role_data_scope_services(query_db, str(add_role_user.role_id), data_scope_sql) @@ -261,12 +289,15 @@ async def add_system_role_user( return ResponseUtil.success(msg=add_role_user_result.message) -@role_controller.put('/authUser/cancel', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put( + '/authUser/cancel', + dependencies=[UserInterfaceAuthDependency('system:role:edit')], +) @Log(title='角色管理', business_type=BusinessType.GRANT) async def cancel_system_role_user( request: Request, cancel_user_role: CrudUserRoleModel, - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: cancel_user_role_result = await UserService.delete_user_role_services(query_db, cancel_user_role) logger.info(cancel_user_role_result.message) @@ -274,12 +305,15 @@ async def cancel_system_role_user( return ResponseUtil.success(msg=cancel_user_role_result.message) -@role_controller.put('/authUser/cancelAll', dependencies=[Depends(CheckUserInterfaceAuth('system:role:edit'))]) +@role_controller.put( + '/authUser/cancelAll', + dependencies=[UserInterfaceAuthDependency('system:role:edit')], +) @Log(title='角色管理', business_type=BusinessType.GRANT) async def batch_cancel_system_role_user( request: Request, batch_cancel_user_role: Annotated[CrudUserRoleModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: batch_cancel_user_role_result = await UserService.delete_user_role_services(query_db, batch_cancel_user_role) logger.info(batch_cancel_user_role_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index ed1bffb..acbcdf1 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -1,17 +1,19 @@ -from fastapi import APIRouter, Depends, Request, Response +from fastapi import APIRouter, Request, Response -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import PreAuthDependency from module_admin.entity.vo.server_vo import ServerMonitorModel -from module_admin.service.login_service import LoginService from module_admin.service.server_service import ServerService from utils.log_util import logger from utils.response_util import ResponseUtil -server_controller = APIRouter(prefix='/monitor/server', dependencies=[Depends(LoginService.get_current_user)]) +server_controller = APIRouter(prefix='/monitor/server', dependencies=[PreAuthDependency()]) @server_controller.get( - '', response_model=ServerMonitorModel, dependencies=[Depends(CheckUserInterfaceAuth('monitor:server:list'))] + '', + response_model=ServerMonitorModel, + dependencies=[UserInterfaceAuthDependency('monitor:server:list')], ) async def get_monitor_server_info(request: Request) -> Response: # 获取全量数据 diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index b8cdc5a..f568799 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -3,16 +3,17 @@ from datetime import datetime from typing import Annotated, Literal, Optional, Union import aiofiles -from fastapi import APIRouter, Depends, File, Form, Path, Query, Request, Response, UploadFile +from fastapi import APIRouter, File, Form, Path, Query, Request, Response, UploadFile from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.data_scope import GetDataScope -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.data_scope import DataScopeDependency +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType from config.env import UploadConfig -from config.get_db import get_db from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.user_vo import ( AddUserModel, @@ -31,7 +32,6 @@ from module_admin.entity.vo.user_vo import ( UserRoleResponseModel, ) from module_admin.service.dept_service import DeptService -from module_admin.service.login_service import LoginService from module_admin.service.role_service import RoleService from module_admin.service.user_service import UserService from utils.common_util import bytes2file_response @@ -41,14 +41,17 @@ from utils.pwd_util import PwdUtil from utils.response_util import ResponseUtil from utils.upload_util import UploadUtil -user_controller = APIRouter(prefix='/system/user', dependencies=[Depends(LoginService.get_current_user)]) +user_controller = APIRouter(prefix='/system/user', dependencies=[PreAuthDependency()]) -@user_controller.get('/deptTree', dependencies=[Depends(CheckUserInterfaceAuth('system:user:list'))]) +@user_controller.get( + '/deptTree', + dependencies=[UserInterfaceAuthDependency('system:user:list')], +) async def get_system_dept_tree( request: Request, - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql) logger.info('获取成功') @@ -57,13 +60,15 @@ async def get_system_dept_tree( @user_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('system:user:list')], ) async def get_system_user_list( request: Request, user_page_query: Annotated[UserPageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: # 获取分页数据 user_page_query_result = await UserService.get_user_list_services( @@ -74,16 +79,19 @@ async def get_system_user_list( return ResponseUtil.success(model_content=user_page_query_result) -@user_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:user:add'))]) +@user_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('system:user:add')], +) @ValidateFields(validate_model='add_user') @Log(title='用户管理', business_type=BusinessType.INSERT) async def add_system_user( request: Request, add_user: AddUserModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - dept_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], - role_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + dept_data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], + role_data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: if not current_user.user.admin: await DeptService.check_dept_data_scope_services(query_db, add_user.dept_id, dept_data_scope_sql) @@ -101,17 +109,20 @@ async def add_system_user( return ResponseUtil.success(msg=add_user_result.message) -@user_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))]) +@user_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('system:user:edit')], +) @ValidateFields(validate_model='edit_user') @Log(title='用户管理', business_type=BusinessType.UPDATE) async def edit_system_user( request: Request, edit_user: EditUserModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - user_data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], - dept_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], - role_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + user_data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], + dept_data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], + role_data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: await UserService.check_user_allowed_services(edit_user) if not current_user.user.admin: @@ -128,14 +139,17 @@ async def edit_system_user( return ResponseUtil.success(msg=edit_user_result.message) -@user_controller.delete('/{user_ids}', dependencies=[Depends(CheckUserInterfaceAuth('system:user:remove'))]) +@user_controller.delete( + '/{user_ids}', + dependencies=[UserInterfaceAuthDependency('system:user:remove')], +) @Log(title='用户管理', business_type=BusinessType.DELETE) async def delete_system_user( request: Request, user_ids: Annotated[str, Path(description='需要删除的用户ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: user_id_list = user_ids.split(',') if user_ids else [] if user_id_list: @@ -154,14 +168,17 @@ async def delete_system_user( return ResponseUtil.success(msg=delete_user_result.message) -@user_controller.put('/resetPwd', dependencies=[Depends(CheckUserInterfaceAuth('system:user:resetPwd'))]) +@user_controller.put( + '/resetPwd', + dependencies=[UserInterfaceAuthDependency('system:user:resetPwd')], +) @Log(title='用户管理', business_type=BusinessType.UPDATE) async def reset_system_user_pwd( request: Request, reset_user: EditUserModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: await UserService.check_user_allowed_services(reset_user) if not current_user.user.admin: @@ -180,14 +197,17 @@ async def reset_system_user_pwd( return ResponseUtil.success(msg=edit_user_result.message) -@user_controller.put('/changeStatus', dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))]) +@user_controller.put( + '/changeStatus', + dependencies=[UserInterfaceAuthDependency('system:user:edit')], +) @Log(title='用户管理', business_type=BusinessType.UPDATE) async def change_system_user_status( request: Request, change_user: EditUserModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: await UserService.check_user_allowed_services(change_user) if not current_user.user.admin: @@ -208,8 +228,8 @@ async def change_system_user_status( @user_controller.get('/profile', response_model=UserProfileModel) async def query_detail_system_user_profile( request: Request, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: profile_user_result = await UserService.user_profile_services(query_db, current_user.user.user_id) logger.info(f'获取user_id为{current_user.user.user_id}的信息成功') @@ -218,16 +238,20 @@ async def query_detail_system_user_profile( @user_controller.get( - '/{user_id}', response_model=UserDetailModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:query'))] + '/{user_id}', + response_model=UserDetailModel, + dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @user_controller.get( - '/', response_model=UserDetailModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:query'))] + '/', + response_model=UserDetailModel, + dependencies=[UserInterfaceAuthDependency('system:user:query')], ) async def query_detail_system_user( request: Request, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], user_id: Optional[Union[int, Literal['']]] = '', ) -> Response: if user_id and not current_user.user.admin: @@ -243,8 +267,8 @@ async def query_detail_system_user( async def change_system_user_profile_avatar( request: Request, avatarfile: Annotated[bytes, File()], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: if avatarfile: relative_path = ( @@ -278,8 +302,8 @@ async def change_system_user_profile_avatar( async def change_system_user_profile_info( request: Request, user_info: UserInfoModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_user = EditUserModel( **user_info.model_dump(exclude_unset=True, by_alias=True, exclude={'role_ids', 'post_ids'}), @@ -302,8 +326,8 @@ async def change_system_user_profile_info( async def reset_system_user_password( request: Request, reset_password: ResetPasswordModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: reset_user = ResetUserModel( userId=current_user.user.user_id, @@ -319,16 +343,19 @@ async def reset_system_user_password( return ResponseUtil.success(msg=reset_user_result.message) -@user_controller.post('/importData', dependencies=[Depends(CheckUserInterfaceAuth('system:user:import'))]) +@user_controller.post( + '/importData', + dependencies=[UserInterfaceAuthDependency('system:user:import')], +) @Log(title='用户管理', business_type=BusinessType.IMPORT) async def batch_import_system_user( request: Request, file: Annotated[UploadFile, File(...)], update_support: Annotated[bool, Query(alias='updateSupport')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - user_data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], - dept_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + user_data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], + dept_data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: batch_import_result = await UserService.batch_import_user_services( request, query_db, file, update_support, current_user, user_data_scope_sql, dept_data_scope_sql @@ -338,21 +365,29 @@ async def batch_import_system_user( return ResponseUtil.success(msg=batch_import_result.message) -@user_controller.post('/importTemplate', dependencies=[Depends(CheckUserInterfaceAuth('system:user:import'))]) -async def export_system_user_template(request: Request, query_db: Annotated[AsyncSession, Depends(get_db)]) -> Response: +@user_controller.post( + '/importTemplate', + dependencies=[UserInterfaceAuthDependency('system:user:import')], +) +async def export_system_user_template( + request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()] +) -> Response: user_import_template_result = await UserService.get_user_import_template_services() logger.info('获取成功') return ResponseUtil.streaming(data=bytes2file_response(user_import_template_result)) -@user_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:user:export'))]) +@user_controller.post( + '/export', + dependencies=[UserInterfaceAuthDependency('system:user:export')], +) @Log(title='用户管理', business_type=BusinessType.EXPORT) async def export_system_user_list( request: Request, user_page_query: Annotated[UserPageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], - data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], ) -> Response: # 获取全量数据 user_query_result = await UserService.get_user_list_services( @@ -367,12 +402,12 @@ async def export_system_user_list( @user_controller.get( '/authRole/{user_id}', response_model=UserRoleResponseModel, - dependencies=[Depends(CheckUserInterfaceAuth('system:user:query'))], + dependencies=[UserInterfaceAuthDependency('system:user:query')], ) async def get_system_allocated_role_list( request: Request, user_id: Annotated[int, Path(description='用户ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: user_role_query = UserRoleQueryModel(userId=user_id) user_role_allocated_query_result = await UserService.get_user_role_allocated_list_services( @@ -386,17 +421,17 @@ async def get_system_allocated_role_list( @user_controller.put( '/authRole', response_model=UserRoleResponseModel, - dependencies=[Depends(CheckUserInterfaceAuth('system:user:edit'))], + dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) @Log(title='用户管理', business_type=BusinessType.GRANT) async def update_system_role_user( request: Request, user_id: Annotated[int, Query(alias='userId')], role_ids: Annotated[str, Query(alias='roleIds')], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], - user_data_scope_sql: Annotated[str, Depends(GetDataScope('SysUser'))], - role_data_scope_sql: Annotated[str, Depends(GetDataScope('SysDept'))], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], + user_data_scope_sql: Annotated[str, DataScopeDependency('SysUser')], + role_data_scope_sql: Annotated[str, DataScopeDependency('SysDept')], ) -> Response: if not current_user.user.admin: await UserService.check_user_data_scope_services(query_db, user_id, user_data_scope_sql) diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index 6f5d4c5..d41fc7f 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -1,17 +1,17 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Depends, Path, Query, Request, Response +from fastapi import APIRouter, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckRoleInterfaceAuth, CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import RoleInterfaceAuthDependency, UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType from config.env import GenConfig -from config.get_db import get_db from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService from module_generator.entity.vo.gen_vo import DeleteGenTableModel, EditGenTableModel, GenTablePageQueryModel from module_generator.service.gen_service import GenTableColumnService, GenTableService from utils.common_util import bytes2file_response @@ -19,16 +19,18 @@ from utils.log_util import logger from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -gen_controller = APIRouter(prefix='/tool/gen', dependencies=[Depends(LoginService.get_current_user)]) +gen_controller = APIRouter(prefix='/tool/gen', dependencies=[PreAuthDependency()]) @gen_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) async def get_gen_table_list( request: Request, gen_page_query: Annotated[GenTablePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 gen_page_query_result = await GenTableService.get_gen_table_list_services(query_db, gen_page_query, is_page=True) @@ -38,12 +40,14 @@ async def get_gen_table_list( @gen_controller.get( - '/db/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:list'))] + '/db/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) async def get_gen_db_table_list( request: Request, gen_page_query: Annotated[GenTablePageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 gen_page_query_result = await GenTableService.get_gen_db_table_list_services(query_db, gen_page_query, is_page=True) @@ -52,13 +56,16 @@ async def get_gen_db_table_list( return ResponseUtil.success(model_content=gen_page_query_result) -@gen_controller.post('/importTable', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:import'))]) +@gen_controller.post( + '/importTable', + dependencies=[UserInterfaceAuthDependency('tool:gen:import')], +) @Log(title='代码生成', business_type=BusinessType.IMPORT) async def import_gen_table( request: Request, tables: Annotated[str, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: table_names = tables.split(',') if tables else [] add_gen_table_list = await GenTableService.get_gen_db_table_list_by_name_services(query_db, table_names) @@ -68,14 +75,17 @@ async def import_gen_table( return ResponseUtil.success(msg=add_gen_table_result.message) -@gen_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:edit'))]) +@gen_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], +) @ValidateFields(validate_model='edit_gen_table') @Log(title='代码生成', business_type=BusinessType.UPDATE) async def edit_gen_table( request: Request, edit_gen_table: EditGenTableModel, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: edit_gen_table.update_by = current_user.user.user_name edit_gen_table.update_time = datetime.now() @@ -86,12 +96,15 @@ async def edit_gen_table( return ResponseUtil.success(msg=edit_gen_result.message) -@gen_controller.delete('/{table_ids}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:remove'))]) +@gen_controller.delete( + '/{table_ids}', + dependencies=[UserInterfaceAuthDependency('tool:gen:remove')], +) @Log(title='代码生成', business_type=BusinessType.DELETE) async def delete_gen_table( request: Request, table_ids: Annotated[str, Path(description='需要删除的代码生成业务表ID')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_gen_table = DeleteGenTableModel(tableIds=table_ids) delete_gen_table_result = await GenTableService.delete_gen_table_services(query_db, delete_gen_table) @@ -100,13 +113,16 @@ async def delete_gen_table( return ResponseUtil.success(msg=delete_gen_table_result.message) -@gen_controller.post('/createTable', dependencies=[Depends(CheckRoleInterfaceAuth('admin'))]) +@gen_controller.post( + '/createTable', + dependencies=[RoleInterfaceAuthDependency('admin')], +) @Log(title='创建表', business_type=BusinessType.OTHER) async def create_table( request: Request, sql: Annotated[str, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: create_table_result = await GenTableService.create_table_services(query_db, sql, current_user) logger.info(create_table_result.message) @@ -114,12 +130,15 @@ async def create_table( return ResponseUtil.success(msg=create_table_result.message) -@gen_controller.get('/batchGenCode', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:code'))]) +@gen_controller.get( + '/batchGenCode', + dependencies=[UserInterfaceAuthDependency('tool:gen:code')], +) @Log(title='代码生成', business_type=BusinessType.GENCODE) async def batch_gen_code( request: Request, tables: Annotated[str, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: table_names = tables.split(',') if tables else [] batch_gen_code_result = await GenTableService.batch_gen_code_services(query_db, table_names) @@ -128,12 +147,15 @@ async def batch_gen_code( return ResponseUtil.streaming(data=bytes2file_response(batch_gen_code_result)) -@gen_controller.get('/genCode/{table_name}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:code'))]) +@gen_controller.get( + '/genCode/{table_name}', + dependencies=[UserInterfaceAuthDependency('tool:gen:code')], +) @Log(title='代码生成', business_type=BusinessType.GENCODE) async def gen_code_local( request: Request, table_name: Annotated[str, Path(description='表名称')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: if not GenConfig.allow_overwrite: logger.error('【系统预设】不允许生成文件覆盖到本地') @@ -144,11 +166,14 @@ async def gen_code_local( return ResponseUtil.success(msg=gen_code_local_result.message) -@gen_controller.get('/{table_id}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:query'))]) +@gen_controller.get( + '/{table_id}', + dependencies=[UserInterfaceAuthDependency('tool:gen:query')], +) async def query_detail_gen_table( request: Request, table_id: Annotated[int, Path(description='表编号')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: gen_table = await GenTableService.get_gen_table_by_id_services(query_db, table_id) gen_tables = await GenTableService.get_gen_table_all_services(query_db) @@ -159,11 +184,14 @@ async def query_detail_gen_table( return ResponseUtil.success(data=gen_table_detail_result) -@gen_controller.get('/preview/{table_id}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:preview'))]) +@gen_controller.get( + '/preview/{table_id}', + dependencies=[UserInterfaceAuthDependency('tool:gen:preview')], +) async def preview_code( request: Request, table_id: Annotated[int, Path(description='表编号')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: preview_code_result = await GenTableService.preview_code_services(query_db, table_id) logger.info('获取预览代码成功') @@ -171,12 +199,15 @@ async def preview_code( return ResponseUtil.success(data=preview_code_result) -@gen_controller.get('/synchDb/{table_name}', dependencies=[Depends(CheckUserInterfaceAuth('tool:gen:edit'))]) +@gen_controller.get( + '/synchDb/{table_name}', + dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], +) @Log(title='代码生成', business_type=BusinessType.UPDATE) async def sync_db( request: Request, table_name: Annotated[str, Path(description='表名称')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: sync_db_result = await GenTableService.sync_db_services(query_db, table_name) logger.info(sync_db_result.message) diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index 4c33ca9..f574cf2 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -13,16 +13,16 @@ from datetime import datetime {% endif %} from typing import Annotated -from fastapi import APIRouter, Depends, Form, Path, Query, Request, Response +from fastapi import APIRouter, Form, Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log -from common.aspect.interface_auth import CheckUserInterfaceAuth +from common.aspect.db_seesion import DBSessionDependency +from common.aspect.interface_auth import UserInterfaceAuthDependency +from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from config.get_db import get_db from module_admin.entity.vo.user_vo import CurrentUserModel -from module_admin.service.login_service import LoginService from {{ packageName }}.service.{{ businessName }}_service import {{ BusinessName }}Service from {{ packageName }}.entity.vo.{{ businessName }}_vo import Delete{{ BusinessName }}Model, {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel from utils.common_util import bytes2file_response @@ -31,16 +31,18 @@ from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil -{{ businessName }}_controller = APIRouter(prefix='/{{ moduleName }}/{{ businessName }}', dependencies=[Depends(LoginService.get_current_user)]) +{{ businessName }}_controller = APIRouter(prefix='/{{ moduleName }}/{{ businessName }}', dependencies=[PreAuthDependency()]) @{{ businessName }}_controller.get( - '/list', response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:list'))] + '/list', + response_model=PageResponseModel, + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:list')], ) async def get_{{ moduleName }}_{{ businessName }}_list( request: Request, {% if table.crud or table.sub %}{{ businessName }}_page_query{% elif table.tree %}{{ businessName }}_query{% endif %}: Annotated[{{ BusinessName }}PageQueryModel, Query()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: {% if table.crud or table.sub %} # 获取分页数据 @@ -56,14 +58,16 @@ async def get_{{ moduleName }}_{{ businessName }}_list( {% endif %} -@{{ businessName }}_controller.post('', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:add'))]) +@{{ businessName }}_controller.post( + '', + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:add')]), @ValidateFields(validate_model='add_{{ businessName }}') @Log(title='{{ functionName }}', business_type=BusinessType.INSERT) async def add_{{ moduleName }}_{{ businessName }}( request: Request, add_{{ businessName }}: {{ BusinessName }}Model, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: {% for column in columns %} {% if column.python_field == "createBy" %} @@ -82,14 +86,16 @@ async def add_{{ moduleName }}_{{ businessName }}( return ResponseUtil.success(msg=add_{{ businessName }}_result.message) -@{{ businessName }}_controller.put('', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:edit'))]) +@{{ businessName }}_controller.put( + '', + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:edit')]), @ValidateFields(validate_model='edit_{{ businessName }}') @Log(title='{{ functionName }}', business_type=BusinessType.UPDATE) async def edit_{{ moduleName }}_{{ businessName }}( request: Request, edit_{{ businessName }}: {{ BusinessName }}Model, - query_db: Annotated[AsyncSession, Depends(get_db)], - current_user: Annotated[CurrentUserModel, Depends(LoginService.get_current_user)], + query_db: Annotated[AsyncSession, DBSessionDependency()], + current_user: Annotated[CurrentUserModel, CurrentUserDependency()], ) -> Response: {% for column in columns %} {% if column.python_field == "updateBy" %} @@ -104,12 +110,14 @@ async def edit_{{ moduleName }}_{{ businessName }}( return ResponseUtil.success(msg=edit_{{ businessName }}_result.message) -@{{ businessName }}_controller.delete('/{% raw %}{{% endraw %}{{ pk_field }}s{% raw %}}{% endraw %}', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:remove'))]) +@{{ businessName }}_controller.delete( + '/{% raw %}{{% endraw %}{{ pk_field }}s{% raw %}}{% endraw %}', + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:remove')]), @Log(title='{{ functionName }}', business_type=BusinessType.DELETE) async def delete_{{ moduleName }}_{{ businessName }}( request: Request, {{ pk_field }}s: Annotated[str, Path(description='需要删除的{{ pk_field_comment }}')], - Annotated[AsyncSession, Depends(get_db)], + Annotated[AsyncSession, DBSessionDependency()], ) -> Response: delete_{{ businessName }} = Delete{{ BusinessName }}Model({{ pkField }}s={{ pk_field }}s) delete_{{ businessName }}_result = await {{ BusinessName }}Service.delete_{{ businessName }}_services(query_db, delete_{{ businessName }}) @@ -119,12 +127,14 @@ async def delete_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.get( - '/{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}', response_model={{ BusinessName }}Model, dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:query'))] + '/{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}', + response_model={{ BusinessName }}Model, + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:query')] ) async def query_detail_{{ moduleName }}_{{ businessName }}( request: Request, {{ pk_field }}: Annotated[{{ pkColumn.python_type }}, Path(description='{{ pk_field_comment }}')], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: {{ businessName }}_detail_result = await {{ BusinessName }}Service.{{ businessName }}_detail_services(query_db, {{ pk_field }}) logger.info(f'获取{{ pk_field }}为{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}的信息成功') @@ -132,12 +142,14 @@ async def query_detail_{{ moduleName }}_{{ businessName }}( return ResponseUtil.success(data={{ businessName }}_detail_result) -@{{ businessName }}_controller.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('{{ permissionPrefix }}:export'))]) +@{{ businessName }}_controller.post( + '/export', + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:export')]) @Log(title='{{ functionName }}', business_type=BusinessType.EXPORT) async def export_{{ moduleName }}_{{ businessName }}_list( request: Request, {{ businessName }}_page_query: Annotated[{{ BusinessName }}PageQueryModel, Form()], - query_db: Annotated[AsyncSession, Depends(get_db)], + query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取全量数据 {{ businessName }}_query_result = await {{ BusinessName }}Service.get_{{ businessName }}_list_services(query_db, {{ businessName }}_page_query, is_page=False) From 6565c50e08d07add37c29a3ab03df9cb7993d928 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 17:00:12 +0800 Subject: [PATCH 10/49] =?UTF-8?q?perf:=20=E5=BD=93=E5=89=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E4=BF=A1=E6=81=AF=E4=BD=BF=E7=94=A8=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/common/annotation/log_annotation.py | 7 ++++--- .../module_admin/service/login_service.py | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ruoyi-fastapi-backend/common/annotation/log_annotation.py b/ruoyi-fastapi-backend/common/annotation/log_annotation.py index a0df36a..59a0637 100644 --- a/ruoyi-fastapi-backend/common/annotation/log_annotation.py +++ b/ruoyi-fastapi-backend/common/annotation/log_annotation.py @@ -15,12 +15,13 @@ from starlette.status import HTTP_200_OK from typing_extensions import ParamSpec from user_agents import parse +from common.context import RequestContext from common.enums import BusinessType from config.env import AppConfig from exceptions.exception import LoginException, ServiceException, ServiceWarning from module_admin.entity.vo.log_vo import LogininforModel, OperLogModel from module_admin.service.log_service import LoginLogService, OperationLogService -from module_admin.service.login_service import LoginService +from utils.dependency_util import DependencyUtil from utils.log_util import logger from utils.response_util import ResponseUtil @@ -61,6 +62,7 @@ class Log: # 获取上下文信息 request_name_list = get_function_parameters_name_by_type(func, Request) request = get_function_parameters_value_by_name(func, request_name_list[0], *args, **kwargs) + DependencyUtil.check_exclude_routes(request, err_msg='当前路由不在认证规则内,不可使用Log装饰器') session_name_list = get_function_parameters_name_by_type(func, AsyncSession) query_db = get_function_parameters_value_by_name(func, session_name_list[0], *args, **kwargs) request_method = request.method @@ -122,8 +124,7 @@ class Log: await LoginLogService.add_login_log_services(query_db, LogininforModel(**login_log)) else: - token = request.headers.get('Authorization') - current_user = await LoginService.get_current_user(request, token, query_db) + current_user = RequestContext.get_current_user() oper_name = current_user.user.user_name dept_name = current_user.user.dept.dept_name if current_user.user.dept else None operation_log = OperLogModel( diff --git a/ruoyi-fastapi-backend/module_admin/service/login_service.py b/ruoyi-fastapi-backend/module_admin/service/login_service.py index 6dfe31b..a7834df 100644 --- a/ruoyi-fastapi-backend/module_admin/service/login_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/login_service.py @@ -11,6 +11,7 @@ from sqlalchemy import Row from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant, MenuConstant +from common.context import RequestContext from common.enums import RedisInitKeyConfig from config.env import AppConfig, JwtConfig from config.get_db import get_db @@ -269,6 +270,8 @@ class LoginService: isDefaultModifyPwd=is_default_modify_pwd, isPasswordExpired=is_password_expired, ) + # 设置当前用户信息到上下文 + RequestContext.set_current_user(current_user) return current_user logger.warning('用户token已失效,请重新登录') raise AuthException(data='', message='用户token已失效,请重新登录') From 044fa0f30b4e3f6a29e438b9f6cd52b4b4f9a008 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 17:00:33 +0800 Subject: [PATCH 11/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E6=B8=85=E7=90=86=E4=B8=AD=E9=97=B4=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../middlewares/context_middleware.py | 29 +++++++++++++++++++ ruoyi-fastapi-backend/middlewares/handle.py | 3 ++ 2 files changed, 32 insertions(+) create mode 100644 ruoyi-fastapi-backend/middlewares/context_middleware.py diff --git a/ruoyi-fastapi-backend/middlewares/context_middleware.py b/ruoyi-fastapi-backend/middlewares/context_middleware.py new file mode 100644 index 0000000..89c9054 --- /dev/null +++ b/ruoyi-fastapi-backend/middlewares/context_middleware.py @@ -0,0 +1,29 @@ +from fastapi import FastAPI, Request +from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint +from starlette.responses import Response + +from common.context import RequestContext + + +class ContextCleanupMiddleware(BaseHTTPMiddleware): + """ + 上下文清理中间件 + """ + + async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: + """ + 在每个请求处理完成后清理上下文信息 + """ + response = await call_next(request) + # 请求处理完成后清理所有上下文变量 + RequestContext.clear_all() + return response + + +def add_context_cleanup_middleware(app: FastAPI) -> None: + """ + 添加上下文清理中间件 + + :param app: FastAPI对象 + """ + app.add_middleware(ContextCleanupMiddleware) diff --git a/ruoyi-fastapi-backend/middlewares/handle.py b/ruoyi-fastapi-backend/middlewares/handle.py index bc2aca9..235bc6a 100644 --- a/ruoyi-fastapi-backend/middlewares/handle.py +++ b/ruoyi-fastapi-backend/middlewares/handle.py @@ -1,5 +1,6 @@ from fastapi import FastAPI +from middlewares.context_middleware import add_context_cleanup_middleware from middlewares.cors_middleware import add_cors_middleware from middlewares.gzip_middleware import add_gzip_middleware from middlewares.trace_middleware import add_trace_middleware @@ -9,6 +10,8 @@ def handle_middleware(app: FastAPI) -> None: """ 全局中间件处理 """ + # 加载上下文清理中间件 + add_context_cleanup_middleware(app) # 加载跨域中间件 add_cors_middleware(app) # 加载gzip压缩中间件 From 8f4058977df2d856cccd5499b131284a54041626 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 11 Dec 2025 17:01:53 +0800 Subject: [PATCH 12/49] chore: fastapi -> 0.124.2 --- ruoyi-fastapi-backend/requirements-pg.txt | 2 +- ruoyi-fastapi-backend/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-fastapi-backend/requirements-pg.txt b/ruoyi-fastapi-backend/requirements-pg.txt index a012eac..9a7a059 100644 --- a/ruoyi-fastapi-backend/requirements-pg.txt +++ b/ruoyi-fastapi-backend/requirements-pg.txt @@ -5,7 +5,7 @@ async-lru==2.0.5 asyncpg==0.30.0 bcrypt==5.0.0 DateTime==5.5 -fastapi[all]==0.123.9 +fastapi[all]==0.124.2 loguru==0.7.3 openpyxl==3.1.5 pandas==2.3.2 diff --git a/ruoyi-fastapi-backend/requirements.txt b/ruoyi-fastapi-backend/requirements.txt index 5ae4b97..7cebdb9 100644 --- a/ruoyi-fastapi-backend/requirements.txt +++ b/ruoyi-fastapi-backend/requirements.txt @@ -5,7 +5,7 @@ async-lru==2.0.5 asyncmy==0.2.10 bcrypt==5.0.0 DateTime==5.5 -fastapi[all]==0.123.9 +fastapi[all]==0.124.2 loguru==0.7.3 openpyxl==3.1.5 pandas==2.3.2 From d9245ed2c9bd1aaafc9e8fae8d3d71629d1ca068 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 12 Dec 2025 08:49:55 +0800 Subject: [PATCH 13/49] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8D=95?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E7=99=BB=E5=BD=95=E6=A8=A1=E5=BC=8F=E4=B8=8B?= =?UTF-8?q?=E5=BC=BA=E9=80=80=E5=8A=9F=E8=83=BD=E5=A4=B1=E6=95=88=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20#52?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/module_admin/service/online_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/service/online_service.py b/ruoyi-fastapi-backend/module_admin/service/online_service.py index cf25d4f..8cde457 100644 --- a/ruoyi-fastapi-backend/module_admin/service/online_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/online_service.py @@ -4,7 +4,7 @@ import jwt from fastapi import Request from common.enums import RedisInitKeyConfig -from config.env import JwtConfig +from config.env import AppConfig, JwtConfig from exceptions.exception import ServiceException from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineQueryModel @@ -33,7 +33,7 @@ class OnlineService: for item in access_token_values_list: payload = jwt.decode(item, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm]) online_dict = { - 'token_id': payload.get('session_id'), + 'token_id': payload.get('session_id') if AppConfig.app_same_time_login else payload.get('user_id'), 'user_name': payload.get('user_name'), 'dept_name': payload.get('dept_name'), 'ipaddr': payload.get('login_info').get('ipaddr'), From dc2e255cd21d01a24f5a53ad5292689c5f344f97 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 12 Dec 2025 09:32:18 +0800 Subject: [PATCH 14/49] =?UTF-8?q?fix:=20=E7=A1=AE=E4=BF=9DApschedulerJobs?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E7=B1=BB=E5=9E=8B=E4=B8=8Eapscheduler?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=88=9B=E5=BB=BA=E7=9A=84=E8=A1=A8=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=B1=BB=E5=9E=8B=E4=B8=80=E8=87=B4=20#53?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/module_admin/entity/do/job_do.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py index 6a19665..82ce77b 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py +++ b/ruoyi-fastapi-backend/module_admin/entity/do/job_do.py @@ -1,6 +1,6 @@ from datetime import datetime -from sqlalchemy import CHAR, DOUBLE, BigInteger, Column, DateTime, Index, LargeBinary, String +from sqlalchemy import CHAR, DOUBLE, BigInteger, Column, DateTime, Float, Index, LargeBinary, String, Unicode from config.database import Base from config.env import DataBaseConfig @@ -67,9 +67,11 @@ class ApschedulerJobs(Base): __tablename__ = 'apscheduler_jobs' - id = Column(String(191), primary_key=True, nullable=False) + id = Column(Unicode(191), primary_key=True, nullable=False) next_run_time = Column( - DOUBLE, nullable=True, server_default=SqlalchemyUtil.get_server_default_null(DataBaseConfig.db_type, False) + DOUBLE if DataBaseConfig.db_type == 'mysql' else Float(25), + nullable=True, + server_default=SqlalchemyUtil.get_server_default_null(DataBaseConfig.db_type, False), ) job_state = Column(LargeBinary, nullable=False) From b8dcbdc4481fc894ae91c5103dd1bc17b8ddb7e1 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 12 Dec 2025 17:42:26 +0800 Subject: [PATCH 15/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=85=AC?= =?UTF-8?q?=E5=85=B1vo=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/common/vo.py | 105 +++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 ruoyi-fastapi-backend/common/vo.py diff --git a/ruoyi-fastapi-backend/common/vo.py b/ruoyi-fastapi-backend/common/vo.py new file mode 100644 index 0000000..5a9b49e --- /dev/null +++ b/ruoyi-fastapi-backend/common/vo.py @@ -0,0 +1,105 @@ +from datetime import datetime +from typing import Any, Generic, Optional, TypeVar, Union + +from pydantic import BaseModel, ConfigDict, Field, create_model +from pydantic.alias_generators import to_camel +from typing_extensions import Self + +from common.constant import HttpStatusConstant + +T = TypeVar('T') + + +class CrudResponseModel(BaseModel): + """ + 操作响应模型 + """ + + is_success: bool = Field(description='操作是否成功') + message: str = Field(description='响应信息') + result: Optional[Any] = Field(default=None, description='响应结果') + + +class ResponseBaseModel(BaseModel): + """ + 响应模型 + """ + + code: int = Field(default=HttpStatusConstant.SUCCESS, description='响应码') + msg: str = Field(default='操作成功', description='响应信息') + success: bool = Field(default=True, description='响应是否成功') + time: datetime = Field(default_factory=datetime.now, description='响应时间') + + +class DynamicResponseModel(ResponseBaseModel, Generic[T]): + """ + 动态响应模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + def __class_getitem__(cls, item: Any) -> Union[Any, Self]: + """ + 当使用 DynamicResponseModel[Item] 语法时,动态创建一个包含所有字段的新模型 + """ + # 检查是否已经为该类型创建了模型 + if not hasattr(cls, '_cached_models'): + cls._cached_models = {} + + if item in cls._cached_models: + return cls._cached_models[item] + + # 检查item是否为Pydantic模型 + if not hasattr(item, 'model_fields'): + raise TypeError(f'{item} 不是一个Pydantic模型,请使用Pydantic模型作为泛型参数') + + # 获取ResponseBaseModel的字段 + base_fields = {} + for field_name, field in cls.model_fields.items(): + base_fields[field_name] = (field.annotation, field) + + # 获取泛型类型的字段 + item_fields = {} + for field_name, field in item.model_fields.items(): + item_fields[field_name] = (field.annotation, field) + + # 合并所有字段 + all_fields = {**base_fields, **item_fields} + + # 动态创建新模型 + new_model = create_model( + f'DynamicResponseModel[{item.__name__}]', __base__=cls, __config__=cls.model_config, **all_fields + ) + + # 缓存模型 + cls._cached_models[item] = new_model + + return new_model + + +class PageModel(BaseModel, Generic[T]): + """ + 分页模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + rows: list[T] = Field(description='记录列表') + page_num: int = Field(description='当前页码') + page_size: int = Field(description='每页记录数') + total: int = Field(description='总记录数') + has_next: bool = Field(description='是否有下一页') + + +class PageResponseModel(PageModel, ResponseBaseModel, Generic[T]): + """ + 分页响应模型 + """ + + +class DataResponseModel(ResponseBaseModel, Generic[T]): + """ + 数据响应模型 + """ + + data: T = Field(description='响应数据') From 165667020382f7f3947224c6558012d2e72dd5cc Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 12 Dec 2025 17:44:27 +0800 Subject: [PATCH 16/49] =?UTF-8?q?perf:=20=E5=88=86=E9=A1=B5=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8=E5=85=AC=E5=85=B1?= =?UTF-8?q?vo=E6=A8=A1=E5=9D=97=E7=9A=84PageModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_admin/dao/config_dao.py | 7 +++-- .../module_admin/dao/dict_dao.py | 11 ++++--- .../module_admin/dao/job_dao.py | 7 +++-- .../module_admin/dao/job_log_dao.py | 7 +++-- .../module_admin/dao/log_dao.py | 11 ++++--- .../module_admin/dao/notice_dao.py | 7 +++-- .../module_admin/dao/post_dao.py | 7 +++-- .../module_admin/dao/role_dao.py | 7 +++-- .../module_admin/dao/user_dao.py | 15 ++++----- .../module_admin/service/config_service.py | 4 +-- .../module_admin/service/dict_service.py | 6 ++-- .../module_admin/service/job_log_service.py | 4 +-- .../module_admin/service/job_service.py | 4 +-- .../module_admin/service/log_service.py | 6 ++-- .../module_admin/service/notice_service.py | 4 +-- .../module_admin/service/post_service.py | 4 +-- .../module_admin/service/role_service.py | 12 +++---- .../module_admin/service/user_service.py | 6 ++-- .../module_generator/dao/gen_dao.py | 11 ++++--- .../module_generator/service/gen_service.py | 6 ++-- ruoyi-fastapi-backend/utils/page_util.py | 31 +++++-------------- 21 files changed, 86 insertions(+), 91 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/dao/config_dao.py b/ruoyi-fastapi-backend/module_admin/dao/config_dao.py index 0e63ed3..a12781c 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/config_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/config_dao.py @@ -4,9 +4,10 @@ from typing import Any, Union from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.config_do import SysConfig from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class ConfigDao: @@ -54,7 +55,7 @@ class ConfigDao: @classmethod async def get_config_list( cls, db: AsyncSession, query_object: ConfigPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取参数配置列表信息 @@ -79,7 +80,7 @@ class ConfigDao: .order_by(SysConfig.config_id) .distinct() ) - config_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + config_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py b/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py index eee5236..60841d1 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/dict_dao.py @@ -5,9 +5,10 @@ from typing import Any, Union from sqlalchemy import and_, delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.dict_do import SysDictData, SysDictType from module_admin.entity.vo.dict_vo import DictDataModel, DictDataPageQueryModel, DictTypeModel, DictTypePageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil from utils.time_format_util import list_format_datetime @@ -68,7 +69,7 @@ class DictTypeDao: @classmethod async def get_dict_type_list( cls, db: AsyncSession, query_object: DictTypePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取字典类型列表信息 @@ -93,7 +94,7 @@ class DictTypeDao: .order_by(SysDictType.dict_id) .distinct() ) - dict_type_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + dict_type_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) @@ -185,7 +186,7 @@ class DictDataDao: @classmethod async def get_dict_data_list( cls, db: AsyncSession, query_object: DictDataPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取字典数据列表信息 @@ -204,7 +205,7 @@ class DictDataDao: .order_by(SysDictData.dict_sort) .distinct() ) - dict_data_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + dict_data_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/job_dao.py b/ruoyi-fastapi-backend/module_admin/dao/job_dao.py index 2b73d74..a628b7b 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/job_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/job_dao.py @@ -4,9 +4,10 @@ from typing import Any, Union from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.job_do import SysJob from module_admin.entity.vo.job_vo import JobModel, JobPageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class JobDao: @@ -59,7 +60,7 @@ class JobDao: @classmethod async def get_job_list( cls, db: AsyncSession, query_object: JobPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取定时任务列表信息 @@ -78,7 +79,7 @@ class JobDao: .order_by(SysJob.job_id) .distinct() ) - job_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + job_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py b/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py index 604a7fe..5aa1e7e 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/job_log_dao.py @@ -5,9 +5,10 @@ from sqlalchemy import delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session +from common.vo import PageModel from module_admin.entity.do.job_do import SysJobLog from module_admin.entity.vo.job_vo import JobLogModel, JobLogPageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class JobLogDao: @@ -18,7 +19,7 @@ class JobLogDao: @classmethod async def get_job_log_list( cls, db: AsyncSession, query_object: JobLogPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取定时任务日志列表信息 @@ -43,7 +44,7 @@ class JobLogDao: .order_by(desc(SysJobLog.create_time)) .distinct() ) - job_log_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + job_log_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/log_dao.py b/ruoyi-fastapi-backend/module_admin/dao/log_dao.py index 385b155..48d4cec 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/log_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/log_dao.py @@ -4,10 +4,11 @@ from typing import Any, Union from sqlalchemy import asc, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.log_do import SysLogininfor, SysOperLog from module_admin.entity.vo.log_vo import LogininforModel, LoginLogPageQueryModel, OperLogModel, OperLogPageQueryModel from utils.common_util import SnakeCaseUtil -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil from utils.time_format_util import TimeFormatUtil @@ -19,7 +20,7 @@ class OperationLogDao: @classmethod async def get_operation_log_list( cls, db: AsyncSession, query_object: OperLogPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取操作日志列表信息 @@ -53,7 +54,7 @@ class OperationLogDao: .distinct() .order_by(order_by_column) ) - operation_log_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + operation_log_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) @@ -104,7 +105,7 @@ class LoginLogDao: @classmethod async def get_login_log_list( cls, db: AsyncSession, query_object: LoginLogPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取登录日志列表信息 @@ -139,7 +140,7 @@ class LoginLogDao: .distinct() .order_by(order_by_column) ) - login_log_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + login_log_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py b/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py index b078555..2dcce96 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/notice_dao.py @@ -4,9 +4,10 @@ from typing import Any, Union from sqlalchemy import delete, select, update from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.notice_do import SysNotice from module_admin.entity.vo.notice_vo import NoticeModel, NoticePageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class NoticeDao: @@ -55,7 +56,7 @@ class NoticeDao: @classmethod async def get_notice_list( cls, db: AsyncSession, query_object: NoticePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取通知公告列表信息 @@ -80,7 +81,7 @@ class NoticeDao: .order_by(SysNotice.notice_id) .distinct() ) - notice_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + notice_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/post_dao.py b/ruoyi-fastapi-backend/module_admin/dao/post_dao.py index 3ea0b22..39ec9aa 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/post_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/post_dao.py @@ -3,10 +3,11 @@ from typing import Any, Union from sqlalchemy import delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.post_do import SysPost from module_admin.entity.do.user_do import SysUserPost from module_admin.entity.vo.post_vo import PostModel, PostPageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class PostDao: @@ -72,7 +73,7 @@ class PostDao: @classmethod async def get_post_list( cls, db: AsyncSession, query_object: PostPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取岗位列表信息 @@ -91,7 +92,7 @@ class PostDao: .order_by(SysPost.post_sort) .distinct() ) - post_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + post_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/role_dao.py b/ruoyi-fastapi-backend/module_admin/dao/role_dao.py index cc9366c..0f5d560 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/role_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/role_dao.py @@ -5,12 +5,13 @@ from typing import Any, Union from sqlalchemy import and_, delete, desc, func, or_, select, update # noqa: F401 from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.menu_do import SysMenu from module_admin.entity.do.role_do import SysRole, SysRoleDept, SysRoleMenu from module_admin.entity.do.user_do import SysUser, SysUserRole from module_admin.entity.vo.role_vo import RoleDeptModel, RoleMenuModel, RoleModel, RolePageQueryModel -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class RoleDao: @@ -131,7 +132,7 @@ class RoleDao: @classmethod async def get_role_list( cls, db: AsyncSession, query_object: RolePageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取角色列表信息 @@ -163,7 +164,7 @@ class RoleDao: .order_by(SysRole.role_sort) .distinct() ) - role_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + role_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/dao/user_dao.py b/ruoyi-fastapi-backend/module_admin/dao/user_dao.py index 0442426..f052c7f 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/user_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/user_dao.py @@ -5,6 +5,7 @@ from typing import Any, Union from sqlalchemy import and_, delete, desc, func, or_, select, update from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.menu_do import SysMenu from module_admin.entity.do.post_do import SysPost @@ -18,7 +19,7 @@ from module_admin.entity.vo.user_vo import ( UserRolePageQueryModel, UserRoleQueryModel, ) -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class UserDao: @@ -280,7 +281,7 @@ class UserDao: @classmethod async def get_user_list( cls, db: AsyncSession, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageResponseModel, list[list[dict[str, Any]]]]: + ) -> Union[PageModel, list[list[dict[str, Any]]]]: """ 根据查询参数获取用户列表信息 @@ -325,7 +326,7 @@ class UserDao: .order_by(SysUser.user_id) .distinct() ) - user_list: Union[PageResponseModel, list[list[dict[str, Any]]]] = await PageUtil.paginate( + user_list: Union[PageModel, list[list[dict[str, Any]]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) @@ -408,7 +409,7 @@ class UserDao: @classmethod async def get_user_role_allocated_list_by_role_id( cls, db: AsyncSession, query_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据角色id获取已分配的用户列表信息 @@ -432,7 +433,7 @@ class UserDao: ) .distinct() ) - allocated_user_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + allocated_user_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) @@ -441,7 +442,7 @@ class UserDao: @classmethod async def get_user_role_unallocated_list_by_role_id( cls, db: AsyncSession, query_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据角色id获取未分配的用户列表信息 @@ -473,7 +474,7 @@ class UserDao: ) .distinct() ) - unallocated_user_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + unallocated_user_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_admin/service/config_service.py b/ruoyi-fastapi-backend/module_admin/service/config_service.py index 3c45a5f..eee4e9b 100644 --- a/ruoyi-fastapi-backend/module_admin/service/config_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/config_service.py @@ -6,13 +6,13 @@ from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant from common.enums import RedisInitKeyConfig +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.config_dao import ConfigDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class ConfigService: @@ -23,7 +23,7 @@ class ConfigService: @classmethod async def get_config_list_services( cls, query_db: AsyncSession, query_object: ConfigPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取参数配置列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/dict_service.py b/ruoyi-fastapi-backend/module_admin/service/dict_service.py index d92fcbe..c2a95a6 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dict_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dict_service.py @@ -8,6 +8,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant from common.enums import RedisInitKeyConfig +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.dict_dao import DictDataDao, DictTypeDao from module_admin.entity.do.dict_do import SysDictData @@ -22,7 +23,6 @@ from module_admin.entity.vo.dict_vo import ( ) from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class DictTypeService: @@ -33,7 +33,7 @@ class DictTypeService: @classmethod async def get_dict_type_list_services( cls, query_db: AsyncSession, query_object: DictTypePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取字典类型列表信息service @@ -231,7 +231,7 @@ class DictDataService: @classmethod async def get_dict_data_list_services( cls, query_db: AsyncSession, query_object: DictDataPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取字典数据列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/job_log_service.py b/ruoyi-fastapi-backend/module_admin/service/job_log_service.py index be67b3b..311d4f3 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_log_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_log_service.py @@ -4,12 +4,12 @@ from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session +from common.vo import PageModel from module_admin.dao.job_log_dao import JobLogDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.job_vo import DeleteJobLogModel, JobLogModel, JobLogPageQueryModel from module_admin.service.dict_service import DictDataService from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class JobLogService: @@ -20,7 +20,7 @@ class JobLogService: @classmethod async def get_job_log_list_services( cls, query_db: AsyncSession, query_object: JobLogPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取定时任务日志列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/job_service.py b/ruoyi-fastapi-backend/module_admin/service/job_service.py index 83a9282..c4a01bc 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_service.py @@ -4,6 +4,7 @@ from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant, JobConstant +from common.vo import PageModel from config.get_scheduler import SchedulerUtil from exceptions.exception import ServiceException from module_admin.dao.job_dao import JobDao @@ -13,7 +14,6 @@ from module_admin.service.dict_service import DictDataService from utils.common_util import CamelCaseUtil from utils.cron_util import CronUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel from utils.string_util import StringUtil @@ -25,7 +25,7 @@ class JobService: @classmethod async def get_job_list_services( cls, query_db: AsyncSession, query_object: JobPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取定时任务列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/log_service.py b/ruoyi-fastapi-backend/module_admin/service/log_service.py index b577834..a857da1 100644 --- a/ruoyi-fastapi-backend/module_admin/service/log_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/log_service.py @@ -3,6 +3,7 @@ from typing import Any, Union from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.log_dao import LoginLogDao, OperationLogDao from module_admin.entity.vo.common_vo import CrudResponseModel @@ -17,7 +18,6 @@ from module_admin.entity.vo.log_vo import ( ) from module_admin.service.dict_service import DictDataService from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class OperationLogService: @@ -28,7 +28,7 @@ class OperationLogService: @classmethod async def get_operation_log_list_services( cls, query_db: AsyncSession, query_object: OperLogPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取操作日志列表信息service @@ -155,7 +155,7 @@ class LoginLogService: @classmethod async def get_login_log_list_services( cls, query_db: AsyncSession, query_object: LoginLogPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取登录日志列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/notice_service.py b/ruoyi-fastapi-backend/module_admin/service/notice_service.py index 5949887..14106f6 100644 --- a/ruoyi-fastapi-backend/module_admin/service/notice_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/notice_service.py @@ -3,12 +3,12 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.notice_dao import NoticeDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from utils.common_util import CamelCaseUtil -from utils.page_util import PageResponseModel class NoticeService: @@ -19,7 +19,7 @@ class NoticeService: @classmethod async def get_notice_list_services( cls, query_db: AsyncSession, query_object: NoticePageQueryModel, is_page: bool = True - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取通知公告列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/post_service.py b/ruoyi-fastapi-backend/module_admin/service/post_service.py index cdf93ef..45f0342 100644 --- a/ruoyi-fastapi-backend/module_admin/service/post_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/post_service.py @@ -3,13 +3,13 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.post_dao import PostDao from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class PostService: @@ -20,7 +20,7 @@ class PostService: @classmethod async def get_post_list_services( cls, query_db: AsyncSession, query_object: PostPageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取岗位列表信息service diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index 4662e0d..d5fec77 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -3,6 +3,7 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.role_dao import RoleDao from module_admin.dao.user_dao import UserDao @@ -19,7 +20,6 @@ from module_admin.entity.vo.role_vo import ( from module_admin.entity.vo.user_vo import UserInfoModel, UserRolePageQueryModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class RoleService: @@ -58,7 +58,7 @@ class RoleService: @classmethod async def get_role_list_services( cls, query_db: AsyncSession, query_object: RolePageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取角色列表信息service @@ -306,7 +306,7 @@ class RoleService: @classmethod async def get_role_user_allocated_list_services( cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> PageResponseModel: + ) -> PageModel: """ 根据角色id获取已分配用户列表 @@ -319,7 +319,7 @@ class RoleService: query_user_list = await UserDao.get_user_role_allocated_list_by_role_id( query_db, page_object, data_scope_sql, is_page ) - allocated_list = PageResponseModel( + allocated_list = PageModel( **{ **query_user_list.model_dump(by_alias=True), 'rows': [UserInfoModel(**row) for row in query_user_list.rows], @@ -331,7 +331,7 @@ class RoleService: @classmethod async def get_role_user_unallocated_list_services( cls, query_db: AsyncSession, page_object: UserRolePageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> PageResponseModel: + ) -> PageModel: """ 根据角色id获取未分配用户列表 @@ -344,7 +344,7 @@ class RoleService: query_user_list = await UserDao.get_user_role_unallocated_list_by_role_id( query_db, page_object, data_scope_sql, is_page ) - unallocated_list = PageResponseModel( + unallocated_list = PageModel( **{ **query_user_list.model_dump(by_alias=True), 'rows': [UserInfoModel(**row) for row in query_user_list.rows], diff --git a/ruoyi-fastapi-backend/module_admin/service/user_service.py b/ruoyi-fastapi-backend/module_admin/service/user_service.py index aaefc00..71270ee 100644 --- a/ruoyi-fastapi-backend/module_admin/service/user_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/user_service.py @@ -7,6 +7,7 @@ from fastapi import Request, UploadFile from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant +from common.vo import PageModel from exceptions.exception import ServiceException from module_admin.dao.user_dao import UserDao from module_admin.entity.do.user_do import SysUserRole @@ -36,7 +37,6 @@ from module_admin.service.post_service import PostService from module_admin.service.role_service import RoleService from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel from utils.pwd_util import PwdUtil @@ -48,7 +48,7 @@ class UserService: @classmethod async def get_user_list_services( cls, query_db: AsyncSession, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取用户列表信息service @@ -60,7 +60,7 @@ class UserService: """ query_result = await UserDao.get_user_list(query_db, query_object, data_scope_sql, is_page) if is_page: - user_list_result = PageResponseModel( + user_list_result = PageModel( **{ **query_result.model_dump(by_alias=True), 'rows': [{**row[0], 'dept': row[1]} for row in query_result.rows], diff --git a/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py b/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py index ae4fc9b..d490ca2 100644 --- a/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py +++ b/ruoyi-fastapi-backend/module_generator/dao/gen_dao.py @@ -7,6 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from sqlglot.expressions import Expression +from common.vo import PageModel from config.env import DataBaseConfig from module_generator.entity.do.gen_do import GenTable, GenTableColumn from module_generator.entity.vo.gen_vo import ( @@ -16,7 +17,7 @@ from module_generator.entity.vo.gen_vo import ( GenTableModel, GenTablePageQueryModel, ) -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class GenTableDao: @@ -94,7 +95,7 @@ class GenTableDao: @classmethod async def get_gen_table_list( cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取代码生成业务表列表信息 @@ -122,7 +123,7 @@ class GenTableDao: ) .distinct() ) - gen_table_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + gen_table_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) @@ -131,7 +132,7 @@ class GenTableDao: @classmethod async def get_gen_db_table_list( cls, db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取数据库列表信息 @@ -185,7 +186,7 @@ class GenTableDao: query = select( text(query_sql).bindparams(**query_object.model_dump(exclude_none=True, exclude={'page_num', 'page_size'})) ) - gen_db_table_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + gen_db_table_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_generator/service/gen_service.py b/ruoyi-fastapi-backend/module_generator/service/gen_service.py index a46bc7b..14b31f8 100644 --- a/ruoyi-fastapi-backend/module_generator/service/gen_service.py +++ b/ruoyi-fastapi-backend/module_generator/service/gen_service.py @@ -11,6 +11,7 @@ from sqlglot import parse as sqlglot_parse from sqlglot.expressions import Add, Alter, Create, Delete, Drop, Expression, Insert, Table, TruncateTable, Update from common.constant import GenConstant +from common.vo import PageModel from config.env import DataBaseConfig, GenConfig from exceptions.exception import ServiceException from module_admin.entity.vo.common_vo import CrudResponseModel @@ -25,7 +26,6 @@ from module_generator.entity.vo.gen_vo import ( ) from utils.common_util import CamelCaseUtil from utils.gen_util import GenUtils -from utils.page_util import PageResponseModel from utils.template_util import TemplateInitializer, TemplateUtils @@ -37,7 +37,7 @@ class GenTableService: @classmethod async def get_gen_table_list_services( cls, query_db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取代码生成业务表列表信息service @@ -53,7 +53,7 @@ class GenTableService: @classmethod async def get_gen_db_table_list_services( cls, query_db: AsyncSession, query_object: GenTablePageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取数据库列表信息service diff --git a/ruoyi-fastapi-backend/utils/page_util.py b/ruoyi-fastapi-backend/utils/page_util.py index 29b7f38..ba75f70 100644 --- a/ruoyi-fastapi-backend/utils/page_util.py +++ b/ruoyi-fastapi-backend/utils/page_util.py @@ -1,35 +1,20 @@ import math -from typing import Any, Optional, Union +from typing import Any, Union -from pydantic import BaseModel, ConfigDict -from pydantic.alias_generators import to_camel from sqlalchemy import Row, Select, func, select from sqlalchemy.ext.asyncio import AsyncSession +from common.vo import PageModel from utils.common_util import CamelCaseUtil -class PageResponseModel(BaseModel): - """ - 列表分页查询返回模型 - """ - - model_config = ConfigDict(alias_generator=to_camel) - - rows: list = [] - page_num: Optional[int] = None - page_size: Optional[int] = None - total: int - has_next: Optional[bool] = None - - class PageUtil: """ 分页工具类 """ @classmethod - def get_page_obj(cls, data_list: list, page_num: int, page_size: int) -> PageResponseModel: + def get_page_obj(cls, data_list: list, page_num: int, page_size: int) -> PageModel: """ 输入数据列表data_list和分页信息,返回分页数据列表结果 @@ -46,7 +31,7 @@ class PageUtil: paginated_data = data_list[start:end] has_next = math.ceil(len(data_list) / page_size) > page_num - result = PageResponseModel( + result = PageModel[Any]( rows=paginated_data, pageNum=page_num, pageSize=page_size, total=len(data_list), hasNext=has_next ) @@ -55,7 +40,7 @@ class PageUtil: @classmethod async def paginate( cls, db: AsyncSession, query: Select, page_num: int, page_size: int, is_page: bool = False - ) -> Union[PageResponseModel, list[Union[dict[str, Any], list[dict[Any, Any]]]]]: + ) -> Union[PageModel, list[Union[dict[str, Any], list[dict[Any, Any]]]]]: """ 输入查询语句和分页信息,返回分页数据列表结果 @@ -76,7 +61,7 @@ class PageUtil: else: paginated_data.append(row) has_next = math.ceil(total / page_size) > page_num - result = PageResponseModel( + result = PageModel[Any]( rows=CamelCaseUtil.transform_result(paginated_data), pageNum=page_num, pageSize=page_size, @@ -96,7 +81,7 @@ class PageUtil: return result -def get_page_obj(data_list: list, page_num: int, page_size: int) -> PageResponseModel: +def get_page_obj(data_list: list, page_num: int, page_size: int) -> PageModel: """ 输入数据列表data_list和分页信息,返回分页数据列表结果 @@ -113,7 +98,7 @@ def get_page_obj(data_list: list, page_num: int, page_size: int) -> PageResponse paginated_data = data_list[start:end] has_next = math.ceil(len(data_list) / page_size) > page_num - result = PageResponseModel( + result = PageModel[Any]( rows=paginated_data, pageNum=page_num, pageSize=page_size, total=len(data_list), hasNext=has_next ) From 1f51b628af876b573ebd39608499726ac8f20094 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 12 Dec 2025 17:44:54 +0800 Subject: [PATCH 17/49] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96API=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=9A=84=E5=93=8D=E5=BA=94=E6=A8=A1=E5=9E=8B=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/config_controller.py | 15 +++++++--- .../controller/dict_controller.py | 27 ++++++++++++----- .../module_admin/controller/job_controller.py | 20 +++++++++---- .../module_admin/controller/log_controller.py | 13 +++++++-- .../controller/notice_controller.py | 9 ++++-- .../controller/online_controller.py | 7 +++-- .../controller/post_controller.py | 9 ++++-- .../controller/role_controller.py | 20 +++++++++---- .../controller/user_controller.py | 29 ++++++++++++++----- .../controller/gen_controller.py | 2 +- 10 files changed, 108 insertions(+), 43 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index e216269..2befefb 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -10,12 +10,12 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.config_service import ConfigService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil config_controller = APIRouter(prefix='/system/config', dependencies=[PreAuthDependency()]) @@ -23,7 +23,7 @@ config_controller = APIRouter(prefix='/system/config', dependencies=[PreAuthDepe @config_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[ConfigModel], dependencies=[UserInterfaceAuthDependency('system:config:list')], ) async def get_system_config_list( @@ -40,6 +40,7 @@ async def get_system_config_list( @config_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:add')], ) @ValidateFields(validate_model='add_config') @@ -62,6 +63,7 @@ async def add_system_config( @config_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:edit')], ) @ValidateFields(validate_model='edit_config') @@ -82,6 +84,7 @@ async def edit_system_config( @config_controller.delete( '/refreshCache', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:remove')], ) @Log(title='参数管理', business_type=BusinessType.UPDATE) @@ -97,6 +100,7 @@ async def refresh_system_config( @config_controller.delete( '/{config_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:remove')], ) @Log(title='参数管理', business_type=BusinessType.DELETE) @@ -114,7 +118,7 @@ async def delete_system_config( @config_controller.get( '/{config_id}', - response_model=ConfigModel, + response_model=DataResponseModel[ConfigModel], dependencies=[UserInterfaceAuthDependency('system:config:query')], ) async def query_detail_system_config( @@ -128,7 +132,10 @@ async def query_detail_system_config( return ResponseUtil.success(data=config_detail_result) -@config_controller.get('/configKey/{config_key}') +@config_controller.get( + '/configKey/{config_key}', + response_model=ResponseBaseModel, +) async def query_system_config(request: Request, config_key: str) -> Response: # 获取全量数据 config_query_result = await ConfigService.query_config_list_from_cache_services(request.app.state.redis, config_key) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index dd319d4..310d00a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -10,6 +10,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.dict_vo import ( DeleteDictDataModel, DeleteDictTypeModel, @@ -22,7 +23,6 @@ from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.dict_service import DictDataService, DictTypeService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil dict_controller = APIRouter(prefix='/system/dict', dependencies=[PreAuthDependency()]) @@ -30,7 +30,7 @@ dict_controller = APIRouter(prefix='/system/dict', dependencies=[PreAuthDependen @dict_controller.get( '/type/list', - response_model=PageResponseModel, + response_model=PageResponseModel[DictTypeModel], dependencies=[UserInterfaceAuthDependency('system:dict:list')], ) async def get_system_dict_type_list( @@ -49,6 +49,7 @@ async def get_system_dict_type_list( @dict_controller.post( '/type', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:add')], ) @ValidateFields(validate_model='add_dict_type') @@ -71,6 +72,7 @@ async def add_system_dict_type( @dict_controller.put( '/type', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:edit')], ) @ValidateFields(validate_model='edit_dict_type') @@ -91,6 +93,7 @@ async def edit_system_dict_type( @dict_controller.delete( '/type/refreshCache', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:remove')], ) @Log(title='字典类型', business_type=BusinessType.UPDATE) @@ -103,6 +106,7 @@ async def refresh_system_dict(request: Request, query_db: Annotated[AsyncSession @dict_controller.delete( '/type/{dict_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:remove')], ) @Log(title='字典类型', business_type=BusinessType.DELETE) @@ -118,7 +122,10 @@ async def delete_system_dict_type( return ResponseUtil.success(msg=delete_dict_type_result.message) -@dict_controller.get('/type/optionselect', response_model=list[DictTypeModel]) +@dict_controller.get( + '/type/optionselect', + response_model=DataResponseModel[list[DictTypeModel]], +) async def query_system_dict_type_options( request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()] ) -> Response: @@ -132,7 +139,7 @@ async def query_system_dict_type_options( @dict_controller.get( '/type/{dict_id}', - response_model=DictTypeModel, + response_model=DataResponseModel[DictTypeModel], dependencies=[UserInterfaceAuthDependency('system:dict:query')], ) async def query_detail_system_dict_type( @@ -166,7 +173,10 @@ async def export_system_dict_type_list( return ResponseUtil.streaming(data=bytes2file_response(dict_type_export_result)) -@dict_controller.get('/data/type/{dict_type}') +@dict_controller.get( + '/data/type/{dict_type}', + response_model=DataResponseModel[list[DictDataModel]], +) async def query_system_dict_type_data( request: Request, dict_type: Annotated[str, Path(description='字典类型')], @@ -183,7 +193,7 @@ async def query_system_dict_type_data( @dict_controller.get( '/data/list', - response_model=PageResponseModel, + response_model=PageResponseModel[DictDataModel], dependencies=[UserInterfaceAuthDependency('system:dict:list')], ) async def get_system_dict_data_list( @@ -202,6 +212,7 @@ async def get_system_dict_data_list( @dict_controller.post( '/data', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:add')], ) @ValidateFields(validate_model='add_dict_data') @@ -224,6 +235,7 @@ async def add_system_dict_data( @dict_controller.put( '/data', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:edit')], ) @ValidateFields(validate_model='edit_dict_data') @@ -244,6 +256,7 @@ async def edit_system_dict_data( @dict_controller.delete( '/data/{dict_codes}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:remove')], ) @Log(title='字典数据', business_type=BusinessType.DELETE) @@ -261,7 +274,7 @@ async def delete_system_dict_data( @dict_controller.get( '/data/{dict_code}', - response_model=DictDataModel, + response_model=DataResponseModel[DictDataModel], dependencies=[UserInterfaceAuthDependency('system:dict:query')], ) async def query_detail_system_dict_data( diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index 5d656be..34735d2 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -10,10 +10,12 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.job_vo import ( DeleteJobLogModel, DeleteJobModel, EditJobModel, + JobLogModel, JobLogPageQueryModel, JobModel, JobPageQueryModel, @@ -23,7 +25,6 @@ from module_admin.service.job_log_service import JobLogService from module_admin.service.job_service import JobService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil job_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()]) @@ -31,7 +32,7 @@ job_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()] @job_controller.get( '/job/list', - response_model=PageResponseModel, + response_model=PageResponseModel[JobModel], dependencies=[UserInterfaceAuthDependency('monitor:job:list')], ) async def get_system_job_list( @@ -40,14 +41,15 @@ async def get_system_job_list( query_db: Annotated[AsyncSession, DBSessionDependency()], ) -> Response: # 获取分页数据 - notice_page_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=True) + job_page_query_result = await JobService.get_job_list_services(query_db, job_page_query, is_page=True) logger.info('获取成功') - return ResponseUtil.success(model_content=notice_page_query_result) + return ResponseUtil.success(model_content=job_page_query_result) @job_controller.post( '/job', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:add')], ) @ValidateFields(validate_model='add_job') @@ -70,6 +72,7 @@ async def add_system_job( @job_controller.put( '/job', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:edit')], ) @ValidateFields(validate_model='edit_job') @@ -90,6 +93,7 @@ async def edit_system_job( @job_controller.put( '/job/changeStatus', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')], ) @Log(title='定时任务', business_type=BusinessType.UPDATE) @@ -114,6 +118,7 @@ async def change_system_job_status( @job_controller.put( '/job/run', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')], ) @Log(title='定时任务', business_type=BusinessType.UPDATE) @@ -130,6 +135,7 @@ async def execute_system_job( @job_controller.delete( '/job/{job_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], ) @Log(title='定时任务', business_type=BusinessType.DELETE) @@ -147,7 +153,7 @@ async def delete_system_job( @job_controller.get( '/job/{job_id}', - response_model=JobModel, + response_model=DataResponseModel[JobModel], dependencies=[UserInterfaceAuthDependency('monitor:job:query')], ) async def query_detail_system_job( @@ -181,7 +187,7 @@ async def export_system_job_list( @job_controller.get( '/jobLog/list', - response_model=PageResponseModel, + response_model=PageResponseModel[JobLogModel], dependencies=[UserInterfaceAuthDependency('monitor:job:list')], ) async def get_system_job_log_list( @@ -200,6 +206,7 @@ async def get_system_job_log_list( @job_controller.delete( '/jobLog/clean', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], ) @Log(title='定时任务调度日志', business_type=BusinessType.CLEAN) @@ -215,6 +222,7 @@ async def clear_system_job_log( @job_controller.delete( '/jobLog/{job_log_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], ) @Log(title='定时任务调度日志', business_type=BusinessType.DELETE) diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index c9238a2..adb497f 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -8,17 +8,19 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType +from common.vo import PageResponseModel, ResponseBaseModel from module_admin.entity.vo.log_vo import ( DeleteLoginLogModel, DeleteOperLogModel, + LogininforModel, LoginLogPageQueryModel, + OperLogModel, OperLogPageQueryModel, UnlockUser, ) from module_admin.service.log_service import LoginLogService, OperationLogService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil log_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()]) @@ -26,7 +28,7 @@ log_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()] @log_controller.get( '/operlog/list', - response_model=PageResponseModel, + response_model=PageResponseModel[OperLogModel], dependencies=[UserInterfaceAuthDependency('monitor:operlog:list')], ) async def get_system_operation_log_list( @@ -45,6 +47,7 @@ async def get_system_operation_log_list( @log_controller.delete( '/operlog/clean', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')], ) @Log(title='操作日志', business_type=BusinessType.CLEAN) @@ -59,6 +62,7 @@ async def clear_system_operation_log( @log_controller.delete( '/operlog/{oper_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')], ) @Log(title='操作日志', business_type=BusinessType.DELETE) @@ -100,7 +104,7 @@ async def export_system_operation_log_list( @log_controller.get( '/logininfor/list', - response_model=PageResponseModel, + response_model=PageResponseModel[LogininforModel], dependencies=[UserInterfaceAuthDependency('monitor:logininfor:list')], ) async def get_system_login_log_list( @@ -119,6 +123,7 @@ async def get_system_login_log_list( @log_controller.delete( '/logininfor/clean', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')], ) @Log(title='登录日志', business_type=BusinessType.CLEAN) @@ -133,6 +138,7 @@ async def clear_system_login_log( @log_controller.delete( '/logininfor/{info_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')], ) @Log(title='登录日志', business_type=BusinessType.DELETE) @@ -150,6 +156,7 @@ async def delete_system_login_log( @log_controller.get( '/logininfor/unlock/{user_name}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:unlock')], ) @Log(title='账户解锁', business_type=BusinessType.OTHER) diff --git a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py index e4987d2..c0351d9 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py @@ -10,11 +10,11 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.notice_service import NoticeService from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil notice_controller = APIRouter(prefix='/system/notice', dependencies=[PreAuthDependency()]) @@ -22,7 +22,7 @@ notice_controller = APIRouter(prefix='/system/notice', dependencies=[PreAuthDepe @notice_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[NoticeModel], dependencies=[UserInterfaceAuthDependency('system:notice:list')], ) async def get_system_notice_list( @@ -39,6 +39,7 @@ async def get_system_notice_list( @notice_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:notice:add')], ) @ValidateFields(validate_model='add_notice') @@ -61,6 +62,7 @@ async def add_system_notice( @notice_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:notice:edit')], ) @ValidateFields(validate_model='edit_notice') @@ -81,6 +83,7 @@ async def edit_system_notice( @notice_controller.delete( '/{notice_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:notice:remove')], ) @Log(title='通知公告', business_type=BusinessType.DELETE) @@ -98,7 +101,7 @@ async def delete_system_notice( @notice_controller.get( '/{notice_id}', - response_model=NoticeModel, + response_model=DataResponseModel[NoticeModel], dependencies=[UserInterfaceAuthDependency('system:notice:query')], ) async def query_detail_system_post( diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index b84f1bf..8a01f56 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -8,10 +8,10 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType -from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineQueryModel +from common.vo import PageResponseModel, ResponseBaseModel +from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineModel, OnlineQueryModel from module_admin.service.online_service import OnlineService from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil online_controller = APIRouter(prefix='/monitor/online', dependencies=[PreAuthDependency()]) @@ -19,7 +19,7 @@ online_controller = APIRouter(prefix='/monitor/online', dependencies=[PreAuthDep @online_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[OnlineModel], dependencies=[UserInterfaceAuthDependency('monitor:online:list')], ) async def get_monitor_online_list( @@ -37,6 +37,7 @@ async def get_monitor_online_list( @online_controller.delete( '/{token_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:online:forceLogout')], ) @Log(title='在线用户', business_type=BusinessType.FORCE) diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index c03f40b..adfce48 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -10,12 +10,12 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.post_service import PostService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil post_controller = APIRouter(prefix='/system/post', dependencies=[PreAuthDependency()]) @@ -23,7 +23,7 @@ post_controller = APIRouter(prefix='/system/post', dependencies=[PreAuthDependen @post_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[PostModel], dependencies=[UserInterfaceAuthDependency('system:post:list')], ) async def get_system_post_list( @@ -40,6 +40,7 @@ async def get_system_post_list( @post_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:post:add')], ) @ValidateFields(validate_model='add_post') @@ -62,6 +63,7 @@ async def add_system_post( @post_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:post:edit')], ) @ValidateFields(validate_model='edit_post') @@ -82,6 +84,7 @@ async def edit_system_post( @post_controller.delete( '/{post_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:post:remove')], ) @Log(title='岗位管理', business_type=BusinessType.DELETE) @@ -99,7 +102,7 @@ async def delete_system_post( @post_controller.get( '/{post_id}', - response_model=PostModel, + response_model=DataResponseModel[PostModel], dependencies=[UserInterfaceAuthDependency('system:post:query')], ) async def query_detail_system_post( diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index e5fe7a2..f3ca39e 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -11,15 +11,15 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.role_vo import AddRoleModel, DeleteRoleModel, RoleModel, RolePageQueryModel -from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserRolePageQueryModel +from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserModel, UserRolePageQueryModel from module_admin.service.dept_service import DeptService from module_admin.service.role_service import RoleService from module_admin.service.user_service import UserService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil role_controller = APIRouter(prefix='/system/role', dependencies=[PreAuthDependency()]) @@ -45,7 +45,7 @@ async def get_system_role_dept_tree( @role_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[RoleModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_role_list( @@ -64,6 +64,7 @@ async def get_system_role_list( @role_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:add')], ) @ValidateFields(validate_model='add_role') @@ -86,6 +87,7 @@ async def add_system_role( @role_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @ValidateFields(validate_model='edit_role') @@ -110,6 +112,7 @@ async def edit_system_role( @role_controller.put( '/dataScope', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @Log(title='角色管理', business_type=BusinessType.GRANT) @@ -139,6 +142,7 @@ async def edit_system_role_datascope( @role_controller.delete( '/{role_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:remove')], ) @Log(title='角色管理', business_type=BusinessType.DELETE) @@ -164,7 +168,7 @@ async def delete_system_role( @role_controller.get( '/{role_id}', - response_model=RoleModel, + response_model=DataResponseModel[RoleModel], dependencies=[UserInterfaceAuthDependency('system:role:query')], ) async def query_detail_system_role( @@ -205,6 +209,7 @@ async def export_system_role_list( @role_controller.put( '/changeStatus', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @Log(title='角色管理', business_type=BusinessType.UPDATE) @@ -233,7 +238,7 @@ async def reset_system_role_status( @role_controller.get( '/authUser/allocatedList', - response_model=PageResponseModel, + response_model=PageResponseModel[UserModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_allocated_user_list( @@ -252,7 +257,7 @@ async def get_system_allocated_user_list( @role_controller.get( '/authUser/unallocatedList', - response_model=PageResponseModel, + response_model=PageResponseModel[UserModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_unallocated_user_list( @@ -271,6 +276,7 @@ async def get_system_unallocated_user_list( @role_controller.put( '/authUser/selectAll', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @Log(title='角色管理', business_type=BusinessType.GRANT) @@ -291,6 +297,7 @@ async def add_system_role_user( @role_controller.put( '/authUser/cancel', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @Log(title='角色管理', business_type=BusinessType.GRANT) @@ -307,6 +314,7 @@ async def cancel_system_role_user( @role_controller.put( '/authUser/cancelAll', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @Log(title='角色管理', business_type=BusinessType.GRANT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index f568799..1ac0810 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -13,6 +13,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from config.env import UploadConfig from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.user_vo import ( @@ -36,7 +37,6 @@ from module_admin.service.role_service import RoleService from module_admin.service.user_service import UserService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.pwd_util import PwdUtil from utils.response_util import ResponseUtil from utils.upload_util import UploadUtil @@ -81,6 +81,7 @@ async def get_system_user_list( @user_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:add')], ) @ValidateFields(validate_model='add_user') @@ -111,6 +112,7 @@ async def add_system_user( @user_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) @ValidateFields(validate_model='edit_user') @@ -141,6 +143,7 @@ async def edit_system_user( @user_controller.delete( '/{user_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:remove')], ) @Log(title='用户管理', business_type=BusinessType.DELETE) @@ -170,6 +173,7 @@ async def delete_system_user( @user_controller.put( '/resetPwd', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:resetPwd')], ) @Log(title='用户管理', business_type=BusinessType.UPDATE) @@ -199,6 +203,7 @@ async def reset_system_user_pwd( @user_controller.put( '/changeStatus', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) @Log(title='用户管理', business_type=BusinessType.UPDATE) @@ -225,7 +230,10 @@ async def change_system_user_status( return ResponseUtil.success(msg=edit_user_result.message) -@user_controller.get('/profile', response_model=UserProfileModel) +@user_controller.get( + '/profile', + response_model=DynamicResponseModel[UserProfileModel], +) async def query_detail_system_user_profile( request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()], @@ -239,7 +247,7 @@ async def query_detail_system_user_profile( @user_controller.get( '/{user_id}', - response_model=UserDetailModel, + response_model=DataResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @user_controller.get( @@ -297,7 +305,10 @@ async def change_system_user_profile_avatar( return ResponseUtil.failure(msg='上传图片异常,请联系管理员') -@user_controller.put('/profile') +@user_controller.put( + '/profile', + response_model=ResponseBaseModel, +) @Log(title='个人信息', business_type=BusinessType.UPDATE) async def change_system_user_profile_info( request: Request, @@ -321,7 +332,10 @@ async def change_system_user_profile_info( return ResponseUtil.success(msg=edit_user_result.message) -@user_controller.put('/profile/updatePwd') +@user_controller.put( + '/profile/updatePwd', + response_model=ResponseBaseModel, +) @Log(title='个人信息', business_type=BusinessType.UPDATE) async def reset_system_user_password( request: Request, @@ -345,6 +359,7 @@ async def reset_system_user_password( @user_controller.post( '/importData', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:import')], ) @Log(title='用户管理', business_type=BusinessType.IMPORT) @@ -401,7 +416,7 @@ async def export_system_user_list( @user_controller.get( '/authRole/{user_id}', - response_model=UserRoleResponseModel, + response_model=DynamicResponseModel[UserRoleResponseModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) async def get_system_allocated_role_list( @@ -420,7 +435,7 @@ async def get_system_allocated_role_list( @user_controller.put( '/authRole', - response_model=UserRoleResponseModel, + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) @Log(title='用户管理', business_type=BusinessType.GRANT) diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index d41fc7f..faab42b 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -10,13 +10,13 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import RoleInterfaceAuthDependency, UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import PageResponseModel from config.env import GenConfig from module_admin.entity.vo.user_vo import CurrentUserModel from module_generator.entity.vo.gen_vo import DeleteGenTableModel, EditGenTableModel, GenTablePageQueryModel from module_generator.service.gen_service import GenTableColumnService, GenTableService from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil gen_controller = APIRouter(prefix='/tool/gen', dependencies=[PreAuthDependency()]) From e216b97163775fc059b16236ec3641c68052b780 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Sat, 13 Dec 2025 11:20:33 +0800 Subject: [PATCH 18/49] =?UTF-8?q?perf:=20=E4=BB=A3=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=A8=A1=E6=9D=BF=E4=BD=BF=E7=94=A8=E5=85=AC=E5=85=B1?= =?UTF-8?q?vo=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/python/controller.py.jinja2 | 21 ++++++++++++------- .../templates/python/dao.py.jinja2 | 7 ++++--- .../templates/python/service.py.jinja2 | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index f574cf2..56c2dd7 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -22,12 +22,12 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.user_vo import CurrentUserModel from {{ packageName }}.service.{{ businessName }}_service import {{ BusinessName }}Service from {{ packageName }}.entity.vo.{{ businessName }}_vo import Delete{{ BusinessName }}Model, {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel from utils.common_util import bytes2file_response from utils.log_util import logger -from utils.page_util import PageResponseModel from utils.response_util import ResponseUtil @@ -36,7 +36,7 @@ from utils.response_util import ResponseUtil @{{ businessName }}_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[{{ BusinessName }}Model], dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:list')], ) async def get_{{ moduleName }}_{{ businessName }}_list( @@ -60,7 +60,9 @@ async def get_{{ moduleName }}_{{ businessName }}_list( @{{ businessName }}_controller.post( '', - dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:add')]), + response_model=ResponseBaseModel, + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:add')], +) @ValidateFields(validate_model='add_{{ businessName }}') @Log(title='{{ functionName }}', business_type=BusinessType.INSERT) async def add_{{ moduleName }}_{{ businessName }}( @@ -88,7 +90,9 @@ async def add_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.put( '', - dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:edit')]), + response_model=ResponseBaseModel, + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:edit')], +) @ValidateFields(validate_model='edit_{{ businessName }}') @Log(title='{{ functionName }}', business_type=BusinessType.UPDATE) async def edit_{{ moduleName }}_{{ businessName }}( @@ -112,7 +116,9 @@ async def edit_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.delete( '/{% raw %}{{% endraw %}{{ pk_field }}s{% raw %}}{% endraw %}', - dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:remove')]), + response_model=ResponseBaseModel, + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:remove')], +) @Log(title='{{ functionName }}', business_type=BusinessType.DELETE) async def delete_{{ moduleName }}_{{ businessName }}( request: Request, @@ -128,7 +134,7 @@ async def delete_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.get( '/{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}', - response_model={{ BusinessName }}Model, + response_model=DataResponseModel[{{ BusinessName }}Model], dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:query')] ) async def query_detail_{{ moduleName }}_{{ businessName }}( @@ -144,7 +150,8 @@ async def query_detail_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.post( '/export', - dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:export')]) + dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:export')], +) @Log(title='{{ functionName }}', business_type=BusinessType.EXPORT) async def export_{{ moduleName }}_{{ businessName }}_list( request: Request, diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 index 477ee84..60222c4 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/dao.py.jinja2 @@ -15,6 +15,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload {% endif %} +from common.vo import PageModel {% if table.sub %} from {{ packageName }}.entity.do.{{ businessName }}_do import {{ ClassName }}, {{ subClassName }} from {{ packageName }}.entity.vo.{{ businessName }}_vo import {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel, {{ subTable.business_name | capitalize }}Model @@ -22,7 +23,7 @@ from {{ packageName }}.entity.vo.{{ businessName }}_vo import {{ BusinessName }} from {{ packageName }}.entity.do.{{ businessName }}_do import {{ ClassName }} from {{ packageName }}.entity.vo.{{ businessName }}_vo import {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel {% endif %} -from utils.page_util import PageResponseModel, PageUtil +from utils.page_util import PageUtil class {{ BusinessName }}Dao: @@ -89,7 +90,7 @@ class {{ BusinessName }}Dao: @classmethod async def get_{{ businessName }}_list( cls, db: AsyncSession, query_object: {{ BusinessName }}PageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 根据查询参数获取{{ functionName }}列表信息 @@ -137,7 +138,7 @@ class {{ BusinessName }}Dao: .order_by({{ ClassName }}.{{ pk_field }}) .distinct() ) - {{ businessName }}_list: Union[PageResponseModel, list[dict[str, Any]]] = await PageUtil.paginate( + {{ businessName }}_list: Union[PageModel, list[dict[str, Any]]] = await PageUtil.paginate( db, query, query_object.page_num, query_object.page_size, is_page ) diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 index 5608b55..bfd8a2a 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 @@ -10,6 +10,7 @@ from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant +from common.vo import PageModel from exceptions.exception import ServiceException from {{ packageName }}.dao.{{ businessName }}_dao import {{ BusinessName }}Dao from module_admin.entity.vo.common_vo import CrudResponseModel @@ -19,7 +20,6 @@ from module_admin.service.dict_service import DictDataService {% endif %} from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil -from utils.page_util import PageResponseModel class {{ BusinessName }}Service: @@ -30,7 +30,7 @@ class {{ BusinessName }}Service: @classmethod async def get_{{ businessName }}_list_services( cls, query_db: AsyncSession, query_object: {{ BusinessName }}PageQueryModel, is_page: bool = False - ) -> Union[PageResponseModel, list[dict[str, Any]]]: + ) -> Union[PageModel, list[dict[str, Any]]]: """ 获取{{ functionName }}列表信息service From d9a19ce3ee489e2e1a8d3c7d7337849149916325 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Sat, 13 Dec 2025 11:28:43 +0800 Subject: [PATCH 19/49] =?UTF-8?q?perf:=20=E6=93=8D=E4=BD=9C=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E6=A8=A1=E5=9E=8B=E6=94=B9=E4=B8=BA=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=85=AC=E5=85=B1vo=E6=A8=A1=E5=9D=97=E7=9A=84CrudResponseMode?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_admin/controller/login_controller.py | 2 +- .../module_admin/entity/vo/common_vo.py | 12 +----------- .../module_admin/service/cache_service.py | 2 +- .../module_admin/service/common_service.py | 3 ++- .../module_admin/service/config_service.py | 3 +-- .../module_admin/service/dept_service.py | 2 +- .../module_admin/service/dict_service.py | 3 +-- .../module_admin/service/job_log_service.py | 3 +-- .../module_admin/service/job_service.py | 3 +-- .../module_admin/service/log_service.py | 3 +-- .../module_admin/service/login_service.py | 2 +- .../module_admin/service/menu_service.py | 2 +- .../module_admin/service/notice_service.py | 3 +-- .../module_admin/service/online_service.py | 2 +- .../module_admin/service/post_service.py | 3 +-- .../module_admin/service/role_service.py | 3 +-- .../module_admin/service/user_service.py | 3 +-- .../module_generator/service/gen_service.py | 3 +-- .../templates/python/service.py.jinja2 | 3 +-- 19 files changed, 20 insertions(+), 40 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index b00b3e1..4dbb055 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -10,8 +10,8 @@ from common.annotation.log_annotation import Log from common.aspect.db_seesion import DBSessionDependency from common.aspect.pre_auth import CurrentUserDependency from common.enums import BusinessType, RedisInitKeyConfig +from common.vo import CrudResponseModel from config.env import AppConfig, JwtConfig -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.login_vo import Token, UserLogin, UserRegister from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel from module_admin.service.login_service import CustomOAuth2PasswordRequestForm, LoginService, oauth2_scheme diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py index f885c31..c589cd1 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/common_vo.py @@ -1,19 +1,9 @@ -from typing import Any, Optional +from typing import Optional from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel -class CrudResponseModel(BaseModel): - """ - 操作响应模型 - """ - - is_success: bool = Field(description='操作是否成功') - message: str = Field(description='响应信息') - result: Optional[Any] = Field(default=None, description='响应结果') - - class UploadResponseModel(BaseModel): """ 上传响应模型 diff --git a/ruoyi-fastapi-backend/module_admin/service/cache_service.py b/ruoyi-fastapi-backend/module_admin/service/cache_service.py index 6ffb2eb..410f6b8 100644 --- a/ruoyi-fastapi-backend/module_admin/service/cache_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/cache_service.py @@ -1,9 +1,9 @@ from fastapi import Request from common.enums import RedisInitKeyConfig +from common.vo import CrudResponseModel from config.get_redis import RedisUtil from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel -from module_admin.entity.vo.common_vo import CrudResponseModel class CacheService: diff --git a/ruoyi-fastapi-backend/module_admin/service/common_service.py b/ruoyi-fastapi-backend/module_admin/service/common_service.py index b5832ad..254ad9f 100644 --- a/ruoyi-fastapi-backend/module_admin/service/common_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/common_service.py @@ -4,9 +4,10 @@ from datetime import datetime import aiofiles from fastapi import BackgroundTasks, Request, UploadFile +from common.vo import CrudResponseModel from config.env import UploadConfig from exceptions.exception import ServiceException -from module_admin.entity.vo.common_vo import CrudResponseModel, UploadResponseModel +from module_admin.entity.vo.common_vo import UploadResponseModel from utils.upload_util import UploadUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/config_service.py b/ruoyi-fastapi-backend/module_admin/service/config_service.py index eee4e9b..a16828d 100644 --- a/ruoyi-fastapi-backend/module_admin/service/config_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/config_service.py @@ -6,10 +6,9 @@ from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant from common.enums import RedisInitKeyConfig -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.config_dao import ConfigDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/dept_service.py b/ruoyi-fastapi-backend/module_admin/service/dept_service.py index 186ea32..d36b2f4 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dept_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dept_service.py @@ -4,10 +4,10 @@ from typing import Any from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant +from common.vo import CrudResponseModel from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.dept_dao import DeptDao from module_admin.entity.do.dept_do import SysDept -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel from utils.common_util import CamelCaseUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/dict_service.py b/ruoyi-fastapi-backend/module_admin/service/dict_service.py index c2a95a6..9717ac5 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dict_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dict_service.py @@ -8,11 +8,10 @@ from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant from common.enums import RedisInitKeyConfig -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.dict_dao import DictDataDao, DictTypeDao from module_admin.entity.do.dict_do import SysDictData -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.dict_vo import ( DeleteDictDataModel, DeleteDictTypeModel, diff --git a/ruoyi-fastapi-backend/module_admin/service/job_log_service.py b/ruoyi-fastapi-backend/module_admin/service/job_log_service.py index 311d4f3..45f046e 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_log_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_log_service.py @@ -4,9 +4,8 @@ from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from module_admin.dao.job_log_dao import JobLogDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.job_vo import DeleteJobLogModel, JobLogModel, JobLogPageQueryModel from module_admin.service.dict_service import DictDataService from utils.excel_util import ExcelUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/job_service.py b/ruoyi-fastapi-backend/module_admin/service/job_service.py index c4a01bc..7f327bf 100644 --- a/ruoyi-fastapi-backend/module_admin/service/job_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/job_service.py @@ -4,11 +4,10 @@ from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant, JobConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from config.get_scheduler import SchedulerUtil from exceptions.exception import ServiceException from module_admin.dao.job_dao import JobDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.job_vo import DeleteJobModel, EditJobModel, JobModel, JobPageQueryModel from module_admin.service.dict_service import DictDataService from utils.common_util import CamelCaseUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/log_service.py b/ruoyi-fastapi-backend/module_admin/service/log_service.py index a857da1..4e89c54 100644 --- a/ruoyi-fastapi-backend/module_admin/service/log_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/log_service.py @@ -3,10 +3,9 @@ from typing import Any, Union from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.log_dao import LoginLogDao, OperationLogDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.log_vo import ( DeleteLoginLogModel, DeleteOperLogModel, diff --git a/ruoyi-fastapi-backend/module_admin/service/login_service.py b/ruoyi-fastapi-backend/module_admin/service/login_service.py index a7834df..d982925 100644 --- a/ruoyi-fastapi-backend/module_admin/service/login_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/login_service.py @@ -13,6 +13,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant, MenuConstant from common.context import RequestContext from common.enums import RedisInitKeyConfig +from common.vo import CrudResponseModel from config.env import AppConfig, JwtConfig from config.get_db import get_db from exceptions.exception import AuthException, LoginException, ServiceException @@ -21,7 +22,6 @@ from module_admin.dao.user_dao import UserDao from module_admin.entity.do.dept_do import SysDept from module_admin.entity.do.menu_do import SysMenu from module_admin.entity.do.user_do import SysUser -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.login_vo import MenuTreeModel, MetaModel, RouterModel, SmsCode, UserLogin, UserRegister from module_admin.entity.vo.user_vo import AddUserModel, CurrentUserModel, ResetUserModel, TokenData, UserInfoModel from module_admin.service.user_service import UserService diff --git a/ruoyi-fastapi-backend/module_admin/service/menu_service.py b/ruoyi-fastapi-backend/module_admin/service/menu_service.py index 43526bd..1767b69 100644 --- a/ruoyi-fastapi-backend/module_admin/service/menu_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/menu_service.py @@ -4,11 +4,11 @@ from typing import Any, Optional from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant, MenuConstant +from common.vo import CrudResponseModel from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.menu_dao import MenuDao from module_admin.dao.role_dao import RoleDao from module_admin.entity.do.menu_do import SysMenu -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel from module_admin.entity.vo.role_vo import RoleMenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel diff --git a/ruoyi-fastapi-backend/module_admin/service/notice_service.py b/ruoyi-fastapi-backend/module_admin/service/notice_service.py index 14106f6..4c210a8 100644 --- a/ruoyi-fastapi-backend/module_admin/service/notice_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/notice_service.py @@ -3,10 +3,9 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.notice_dao import NoticeDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from utils.common_util import CamelCaseUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/online_service.py b/ruoyi-fastapi-backend/module_admin/service/online_service.py index 8cde457..6ed5070 100644 --- a/ruoyi-fastapi-backend/module_admin/service/online_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/online_service.py @@ -4,9 +4,9 @@ import jwt from fastapi import Request from common.enums import RedisInitKeyConfig +from common.vo import CrudResponseModel from config.env import AppConfig, JwtConfig from exceptions.exception import ServiceException -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineQueryModel from utils.common_util import CamelCaseUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/post_service.py b/ruoyi-fastapi-backend/module_admin/service/post_service.py index 45f0342..c25d462 100644 --- a/ruoyi-fastapi-backend/module_admin/service/post_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/post_service.py @@ -3,10 +3,9 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.post_dao import PostDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from utils.common_util import CamelCaseUtil from utils.excel_util import ExcelUtil diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index d5fec77..c960197 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -3,11 +3,10 @@ from typing import Any, Union from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.role_dao import RoleDao from module_admin.dao.user_dao import UserDao -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.role_vo import ( AddRoleModel, DeleteRoleModel, diff --git a/ruoyi-fastapi-backend/module_admin/service/user_service.py b/ruoyi-fastapi-backend/module_admin/service/user_service.py index 71270ee..9a8bc3c 100644 --- a/ruoyi-fastapi-backend/module_admin/service/user_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/user_service.py @@ -7,11 +7,10 @@ from fastapi import Request, UploadFile from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from module_admin.dao.user_dao import UserDao from module_admin.entity.do.user_do import SysUserRole -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.post_vo import PostPageQueryModel from module_admin.entity.vo.user_vo import ( AddUserModel, diff --git a/ruoyi-fastapi-backend/module_generator/service/gen_service.py b/ruoyi-fastapi-backend/module_generator/service/gen_service.py index 14b31f8..4918d00 100644 --- a/ruoyi-fastapi-backend/module_generator/service/gen_service.py +++ b/ruoyi-fastapi-backend/module_generator/service/gen_service.py @@ -11,10 +11,9 @@ from sqlglot import parse as sqlglot_parse from sqlglot.expressions import Add, Alter, Create, Delete, Drop, Expression, Insert, Table, TruncateTable, Update from common.constant import GenConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from config.env import DataBaseConfig, GenConfig from exceptions.exception import ServiceException -from module_admin.entity.vo.common_vo import CrudResponseModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_generator.dao.gen_dao import GenTableColumnDao, GenTableDao from module_generator.entity.vo.gen_vo import ( diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 index bfd8a2a..c13d8cd 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/service.py.jinja2 @@ -10,10 +10,9 @@ from fastapi import Request from sqlalchemy.ext.asyncio import AsyncSession from common.constant import CommonConstant -from common.vo import PageModel +from common.vo import CrudResponseModel, PageModel from exceptions.exception import ServiceException from {{ packageName }}.dao.{{ businessName }}_dao import {{ BusinessName }}Dao -from module_admin.entity.vo.common_vo import CrudResponseModel from {{ packageName }}.entity.vo.{{ businessName }}_vo import Delete{{ BusinessName }}Model, {{ BusinessName }}Model, {{ BusinessName }}PageQueryModel {% if dicts %} from module_admin.service.dict_service import DictDataService From 40ccb84922189809da484d20899f38aefe401b25 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Mon, 15 Dec 2025 15:02:49 +0800 Subject: [PATCH 20/49] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=89=80?= =?UTF-8?q?=E6=9C=89=E6=8E=A5=E5=8F=A3=E7=9A=84API=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E6=A8=A1=E5=9E=8B=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/cache_controller.py | 11 ++++-- .../controller/captcha_controller.py | 6 ++- .../controller/common_controller.py | 34 +++++++++++++++-- .../controller/config_controller.py | 10 +++++ .../controller/dept_controller.py | 12 ++++-- .../controller/dict_controller.py | 19 ++++++++++ .../module_admin/controller/job_controller.py | 19 ++++++++++ .../module_admin/controller/log_controller.py | 19 ++++++++++ .../controller/login_controller.py | 29 +++++++++++---- .../controller/menu_controller.py | 21 ++++++++--- .../controller/post_controller.py | 10 +++++ .../controller/role_controller.py | 27 +++++++++++--- .../controller/server_controller.py | 3 +- .../controller/user_controller.py | 37 ++++++++++++++++--- .../module_admin/entity/vo/dept_vo.py | 13 +++++++ .../module_admin/entity/vo/menu_vo.py | 13 +++++++ .../module_admin/entity/vo/user_vo.py | 18 +++++++++ .../module_admin/service/dept_service.py | 21 ++++++----- .../module_admin/service/menu_service.py | 19 +++++----- .../module_admin/service/role_service.py | 4 +- .../module_admin/service/user_service.py | 5 ++- .../controller/gen_controller.py | 33 +++++++++++++++-- .../module_generator/entity/vo/gen_vo.py | 33 +++++++++++++++++ .../templates/python/controller.py.jinja2 | 10 +++++ 24 files changed, 363 insertions(+), 63 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index 40b2684..50cb958 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -4,6 +4,7 @@ from fastapi import APIRouter, Path, Request, Response from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency +from common.vo import DataResponseModel, ResponseBaseModel from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.service.cache_service import CacheService from utils.log_util import logger @@ -14,7 +15,7 @@ cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[PreAuthDepen @cache_controller.get( '', - response_model=CacheMonitorModel, + response_model=DataResponseModel[CacheMonitorModel], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_info(request: Request) -> Response: @@ -27,7 +28,7 @@ async def get_monitor_cache_info(request: Request) -> Response: @cache_controller.get( '/getNames', - response_model=list[CacheInfoModel], + response_model=DataResponseModel[list[CacheInfoModel]], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_name(request: Request) -> Response: @@ -40,7 +41,7 @@ async def get_monitor_cache_name(request: Request) -> Response: @cache_controller.get( '/getKeys/{cache_name}', - response_model=list[str], + response_model=DataResponseModel[list[str]], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Path(description='缓存名称')]) -> Response: @@ -53,7 +54,7 @@ async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Pat @cache_controller.get( '/getValue/{cache_name}/{cache_key}', - response_model=CacheInfoModel, + response_model=DataResponseModel[CacheInfoModel], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def get_monitor_cache_value( @@ -83,6 +84,7 @@ async def clear_monitor_cache_name( @cache_controller.delete( '/clearCacheKey/{cache_key}', + response_model= ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Path(description='缓存键')]) -> Response: @@ -94,6 +96,7 @@ async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Pa @cache_controller.delete( '/clearCacheAll', + response_model= ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_all(request: Request) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py index f1ef6c4..2eb6358 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py @@ -4,6 +4,7 @@ from datetime import timedelta from fastapi import APIRouter, Request, Response from common.enums import RedisInitKeyConfig +from common.vo import DynamicResponseModel from module_admin.entity.vo.login_vo import CaptchaCode from module_admin.service.captcha_service import CaptchaService from utils.log_util import logger @@ -12,7 +13,10 @@ from utils.response_util import ResponseUtil captcha_controller = APIRouter() -@captcha_controller.get('/captchaImage') +@captcha_controller.get( + '/captchaImage', + response_model=DynamicResponseModel[CaptchaCode], +) async def get_captcha_image(request: Request) -> Response: captcha_enabled = ( await request.app.state.redis.get(f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.captchaEnabled') == 'true' diff --git a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py index 9d37c8f..182bd8e 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py @@ -1,8 +1,11 @@ from typing import Annotated from fastapi import APIRouter, BackgroundTasks, File, Query, Request, Response, UploadFile +from fastapi.responses import StreamingResponse from common.aspect.pre_auth import PreAuthDependency +from common.vo import DynamicResponseModel +from module_admin.entity.vo.common_vo import UploadResponseModel from module_admin.service.common_service import CommonService from utils.log_util import logger from utils.response_util import ResponseUtil @@ -10,7 +13,10 @@ from utils.response_util import ResponseUtil common_controller = APIRouter(prefix='/common', dependencies=[PreAuthDependency()]) -@common_controller.post('/upload') +@common_controller.post( + '/upload', + response_model=DynamicResponseModel[UploadResponseModel], +) async def common_upload(request: Request, file: Annotated[UploadFile, File(...)]) -> Response: upload_result = await CommonService.upload_service(request, file) logger.info('上传成功') @@ -18,7 +24,18 @@ async def common_upload(request: Request, file: Annotated[UploadFile, File(...)] return ResponseUtil.success(model_content=upload_result.result) -@common_controller.get('/download') +@common_controller.get( + '/download', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, +) async def common_download( request: Request, background_tasks: BackgroundTasks, @@ -31,7 +48,18 @@ async def common_download( return ResponseUtil.streaming(data=download_result.result) -@common_controller.get('/download/resource') +@common_controller.get( + '/download/resource', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, +) async def common_download_resource(request: Request, resource: Annotated[str, Query()]) -> Response: download_resource_result = await CommonService.download_resource_services(resource) logger.info(download_resource_result.message) diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index 2befefb..2515cb5 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -146,6 +147,15 @@ async def query_system_config(request: Request, config_key: str) -> Response: @config_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回参数列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:config:export')], ) @Log(title='参数管理', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index 542e869..8136dcd 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.vo import DataResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.dept_service import DeptService @@ -22,7 +23,7 @@ dept_controller = APIRouter(prefix='/system/dept', dependencies=[PreAuthDependen @dept_controller.get( '/list/exclude/{dept_id}', - response_model=list[DeptModel], + response_model=DataResponseModel[list[DeptModel]], dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) async def get_system_dept_tree_for_edit_option( @@ -40,7 +41,7 @@ async def get_system_dept_tree_for_edit_option( @dept_controller.get( '/list', - response_model=list[DeptModel], + response_model=DataResponseModel[list[DeptModel]], dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) async def get_system_dept_list( @@ -57,6 +58,7 @@ async def get_system_dept_list( @dept_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:add')], ) @ValidateFields(validate_model='add_dept') @@ -74,11 +76,12 @@ async def add_system_dept( add_dept_result = await DeptService.add_dept_services(query_db, add_dept) logger.info(add_dept_result.message) - return ResponseUtil.success(data=add_dept_result) + return ResponseUtil.success(msg=add_dept_result.message) @dept_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:edit')], ) @ValidateFields(validate_model='edit_dept') @@ -102,6 +105,7 @@ async def edit_system_dept( @dept_controller.delete( '/{dept_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:remove')], ) @Log(title='部门管理', business_type=BusinessType.DELETE) @@ -128,7 +132,7 @@ async def delete_system_dept( @dept_controller.get( '/{dept_id}', - response_model=DeptModel, + response_model=DataResponseModel[DeptModel], dependencies=[UserInterfaceAuthDependency('system:dept:query')], ) async def query_detail_system_dept( diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index 310d00a..d7b9803 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -155,6 +156,15 @@ async def query_detail_system_dict_type( @dict_controller.post( '/type/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回字典类型列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:dict:export')], ) @Log(title='字典类型', business_type=BusinessType.EXPORT) @@ -290,6 +300,15 @@ async def query_detail_system_dict_data( @dict_controller.post( '/data/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回字典数据列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:dict:export')], ) @Log(title='字典数据', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index 34735d2..33a4bda 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -169,6 +170,15 @@ async def query_detail_system_job( @job_controller.post( '/job/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回定时任务列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:job:export')], ) @Log(title='定时任务', business_type=BusinessType.EXPORT) @@ -240,6 +250,15 @@ async def delete_system_job_log( @job_controller.post( '/jobLog/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回定时任务日志列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:job:export')], ) @Log(title='定时任务调度日志', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index adb497f..e0a36b4 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -1,6 +1,7 @@ from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log @@ -82,6 +83,15 @@ async def delete_system_operation_log( @log_controller.post( '/operlog/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回操作日志列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:operlog:export')], ) @Log(title='操作日志', business_type=BusinessType.EXPORT) @@ -174,6 +184,15 @@ async def unlock_system_user( @log_controller.post( '/logininfor/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回登录日志列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:export')], ) @Log(title='登录日志', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 4dbb055..7ac208a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -10,9 +10,9 @@ from common.annotation.log_annotation import Log from common.aspect.db_seesion import DBSessionDependency from common.aspect.pre_auth import CurrentUserDependency from common.enums import BusinessType, RedisInitKeyConfig -from common.vo import CrudResponseModel +from common.vo import CrudResponseModel, DataResponseModel, DynamicResponseModel, ResponseBaseModel from config.env import AppConfig, JwtConfig -from module_admin.entity.vo.login_vo import Token, UserLogin, UserRegister +from module_admin.entity.vo.login_vo import RouterModel, Token, UserLogin, UserRegister from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel from module_admin.service.login_service import CustomOAuth2PasswordRequestForm, LoginService, oauth2_scheme from module_admin.service.user_service import UserService @@ -22,7 +22,10 @@ from utils.response_util import ResponseUtil login_controller = APIRouter() -@login_controller.post('/login', response_model=Token) +@login_controller.post( + '/login', + response_model=DynamicResponseModel[Token], +) @Log(title='用户登录', business_type=BusinessType.OTHER, log_type='login') async def login( request: Request, @@ -78,7 +81,10 @@ async def login( return ResponseUtil.success(msg='登录成功', dict_content={'token': access_token}) -@login_controller.get('/getInfo', response_model=CurrentUserModel) +@login_controller.get( + '/getInfo', + response_model=DynamicResponseModel[CurrentUserModel], +) async def get_login_user_info( request: Request, current_user: Annotated[CurrentUserModel, CurrentUserDependency()] ) -> Response: @@ -87,7 +93,10 @@ async def get_login_user_info( return ResponseUtil.success(model_content=current_user) -@login_controller.get('/getRouters') +@login_controller.get( + '/getRouters', + response_model=DataResponseModel[list[RouterModel]], +) async def get_login_user_routers( request: Request, current_user: Annotated[CurrentUserModel, CurrentUserDependency()], @@ -99,7 +108,10 @@ async def get_login_user_routers( return ResponseUtil.success(data=user_routers) -@login_controller.post('/register', response_model=CrudResponseModel) +@login_controller.post( + '/register', + response_model=DataResponseModel[CrudResponseModel], +) async def register_user( request: Request, user_register: UserRegister, @@ -141,7 +153,10 @@ async def register_user( # return ResponseUtil.error(msg=str(e)) -@login_controller.post('/logout') +@login_controller.post( + '/logout', + response_model=ResponseBaseModel, +) async def logout(request: Request, token: Annotated[Optional[str], Depends(oauth2_scheme)]) -> Response: payload = jwt.decode( token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm], options={'verify_exp': False} diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index fd157d1..ec97f1b 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -10,7 +10,9 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel +from common.vo import DataResponseModel, DynamicResponseModel, ResponseBaseModel +from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel, MenuTreeModel +from module_admin.entity.vo.role_vo import RoleMenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from module_admin.service.menu_service import MenuService from utils.log_util import logger @@ -19,7 +21,10 @@ from utils.response_util import ResponseUtil menu_controller = APIRouter(prefix='/system/menu', dependencies=[PreAuthDependency()]) -@menu_controller.get('/treeselect') +@menu_controller.get( + '/treeselect', + response_model=DataResponseModel[list[MenuTreeModel]], +) async def get_system_menu_tree( request: Request, query_db: Annotated[AsyncSession, DBSessionDependency()], @@ -31,7 +36,10 @@ async def get_system_menu_tree( return ResponseUtil.success(data=menu_query_result) -@menu_controller.get('/roleMenuTreeselect/{role_id}') +@menu_controller.get( + '/roleMenuTreeselect/{role_id}', + response_model=DynamicResponseModel[RoleMenuQueryModel], +) async def get_system_role_menu_tree( request: Request, role_id: Annotated[int, Path(description='角色ID')], @@ -46,7 +54,7 @@ async def get_system_role_menu_tree( @menu_controller.get( '/list', - response_model=list[MenuModel], + response_model=DataResponseModel[list[MenuModel]], dependencies=[UserInterfaceAuthDependency('system:menu:list')], ) async def get_system_menu_list( @@ -63,6 +71,7 @@ async def get_system_menu_list( @menu_controller.post( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:add')], ) @ValidateFields(validate_model='add_menu') @@ -85,6 +94,7 @@ async def add_system_menu( @menu_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:edit')], ) @ValidateFields(validate_model='edit_menu') @@ -105,6 +115,7 @@ async def edit_system_menu( @menu_controller.delete( '/{menu_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:remove')], ) @Log(title='菜单管理', business_type=BusinessType.DELETE) @@ -122,7 +133,7 @@ async def delete_system_menu( @menu_controller.get( '/{menu_id}', - response_model=MenuModel, + response_model=DataResponseModel[MenuModel], dependencies=[UserInterfaceAuthDependency('system:menu:query')], ) async def query_detail_system_menu( diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index adfce48..3ea466c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -118,6 +119,15 @@ async def query_detail_system_post( @post_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回岗位列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:post:export')], ) @Log(title='岗位管理', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index f3ca39e..9d3ea2a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,10 +12,16 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel +from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeptModel -from module_admin.entity.vo.role_vo import AddRoleModel, DeleteRoleModel, RoleModel, RolePageQueryModel -from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserModel, UserRolePageQueryModel +from module_admin.entity.vo.role_vo import ( + AddRoleModel, + DeleteRoleModel, + RoleDeptQueryModel, + RoleModel, + RolePageQueryModel, +) +from module_admin.entity.vo.user_vo import CrudUserRoleModel, CurrentUserModel, UserInfoModel, UserRolePageQueryModel from module_admin.service.dept_service import DeptService from module_admin.service.role_service import RoleService from module_admin.service.user_service import UserService @@ -27,6 +34,7 @@ role_controller = APIRouter(prefix='/system/role', dependencies=[PreAuthDependen @role_controller.get( '/deptTree/{role_id}', + response_model=DynamicResponseModel[RoleDeptQueryModel], dependencies=[UserInterfaceAuthDependency('system:role:query')], ) async def get_system_role_dept_tree( @@ -188,6 +196,15 @@ async def query_detail_system_role( @role_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回角色列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:role:export')], ) @Log(title='角色管理', business_type=BusinessType.EXPORT) @@ -238,7 +255,7 @@ async def reset_system_role_status( @role_controller.get( '/authUser/allocatedList', - response_model=PageResponseModel[UserModel], + response_model=PageResponseModel[UserInfoModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_allocated_user_list( @@ -257,7 +274,7 @@ async def get_system_allocated_user_list( @role_controller.get( '/authUser/unallocatedList', - response_model=PageResponseModel[UserModel], + response_model=PageResponseModel[UserInfoModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) async def get_system_unallocated_user_list( diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index acbcdf1..0c20659 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -2,6 +2,7 @@ from fastapi import APIRouter, Request, Response from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency +from common.vo import DataResponseModel from module_admin.entity.vo.server_vo import ServerMonitorModel from module_admin.service.server_service import ServerService from utils.log_util import logger @@ -12,7 +13,7 @@ server_controller = APIRouter(prefix='/monitor/server', dependencies=[PreAuthDep @server_controller.get( '', - response_model=ServerMonitorModel, + response_model=DataResponseModel[ServerMonitorModel], dependencies=[UserInterfaceAuthDependency('monitor:server:list')], ) async def get_monitor_server_info(request: Request) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index 1ac0810..36467af 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -4,6 +4,7 @@ from typing import Annotated, Literal, Optional, Union import aiofiles from fastapi import APIRouter, File, Form, Path, Query, Request, Response, UploadFile +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -15,9 +16,10 @@ from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from config.env import UploadConfig -from module_admin.entity.vo.dept_vo import DeptModel +from module_admin.entity.vo.dept_vo import DeptModel, DeptTreeModel from module_admin.entity.vo.user_vo import ( AddUserModel, + AvatarModel, CrudUserRoleModel, CurrentUserModel, DeleteUserModel, @@ -31,6 +33,7 @@ from module_admin.entity.vo.user_vo import ( UserProfileModel, UserRoleQueryModel, UserRoleResponseModel, + UserRowModel, ) from module_admin.service.dept_service import DeptService from module_admin.service.role_service import RoleService @@ -46,6 +49,7 @@ user_controller = APIRouter(prefix='/system/user', dependencies=[PreAuthDependen @user_controller.get( '/deptTree', + response_model=DataResponseModel[list[DeptTreeModel]], dependencies=[UserInterfaceAuthDependency('system:user:list')], ) async def get_system_dept_tree( @@ -61,7 +65,7 @@ async def get_system_dept_tree( @user_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[UserRowModel], dependencies=[UserInterfaceAuthDependency('system:user:list')], ) async def get_system_user_list( @@ -247,12 +251,12 @@ async def query_detail_system_user_profile( @user_controller.get( '/{user_id}', - response_model=DataResponseModel[UserDetailModel], + response_model=DynamicResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @user_controller.get( '/', - response_model=UserDetailModel, + response_model=DynamicResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) async def query_detail_system_user( @@ -270,7 +274,10 @@ async def query_detail_system_user( return ResponseUtil.success(model_content=detail_user_result) -@user_controller.post('/profile/avatar') +@user_controller.post( + '/profile/avatar', + response_model=DynamicResponseModel[AvatarModel], +) @Log(title='个人信息', business_type=BusinessType.UPDATE) async def change_system_user_profile_avatar( request: Request, @@ -301,7 +308,7 @@ async def change_system_user_profile_avatar( edit_user_result = await UserService.edit_user_services(query_db, edit_user) logger.info(edit_user_result.message) - return ResponseUtil.success(dict_content={'imgUrl': edit_user.avatar}, msg=edit_user_result.message) + return ResponseUtil.success(model_content=AvatarModel(imgUrl=edit_user.avatar), msg=edit_user_result.message) return ResponseUtil.failure(msg='上传图片异常,请联系管理员') @@ -382,6 +389,15 @@ async def batch_import_system_user( @user_controller.post( '/importTemplate', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回导入用户模板excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:user:import')], ) async def export_system_user_template( @@ -395,6 +411,15 @@ async def export_system_user_template( @user_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回用户列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('system:user:export')], ) @Log(title='用户管理', business_type=BusinessType.EXPORT) diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py index 930f820..7b7afa8 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/dept_vo.py @@ -62,6 +62,19 @@ class DeptQueryModel(DeptModel): end_time: Optional[str] = Field(default=None, description='结束时间') +class DeptTreeModel(BaseModel): + """ + 部门树模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + id: int = Field(description='部门id') + label: str = Field(description='部门名称') + parent_id: int = Field(description='父部门id') + children: Optional[list['DeptTreeModel']] = Field(default=None, description='子部门树') + + class DeleteDeptModel(BaseModel): """ 删除部门模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py index b58500c..7b5212a 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/menu_vo.py @@ -77,6 +77,19 @@ class MenuQueryModel(MenuModel): end_time: Optional[str] = Field(default=None, description='结束时间') +class MenuTreeModel(BaseModel): + """ + 菜单树模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + id: int = Field(description='菜单id') + label: str = Field(description='菜单名称') + parent_id: int = Field(description='父菜单id') + children: Optional[list['MenuTreeModel']] = Field(default=None, description='子菜单树') + + class DeleteMenuModel(BaseModel): """ 删除菜单模型 diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py index 887b0f9..0ac0f4e 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py @@ -91,6 +91,14 @@ class UserModel(BaseModel): self.get_phonenumber() +class UserRowModel(UserModel): + """ + 用户列表行数据模型 + """ + + dept: Optional[DeptModel] = Field(default=None, description='部门信息') + + class UserRoleModel(BaseModel): """ 用户和角色关联表对应pydantic模型 @@ -156,6 +164,16 @@ class UserProfileModel(BaseModel): role_group: Union[str, None] = Field(description='角色信息') +class AvatarModel(BaseModel): + """ + 上传头像响应模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + img_url: str = Field(description='头像地址') + + class UserQueryModel(UserModel): """ 用户管理不分页查询模型 diff --git a/ruoyi-fastapi-backend/module_admin/service/dept_service.py b/ruoyi-fastapi-backend/module_admin/service/dept_service.py index d36b2f4..b939c41 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dept_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dept_service.py @@ -8,7 +8,7 @@ from common.vo import CrudResponseModel from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.dept_dao import DeptDao from module_admin.entity.do.dept_do import SysDept -from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel +from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptTreeModel from utils.common_util import CamelCaseUtil @@ -20,7 +20,7 @@ class DeptService: @classmethod async def get_dept_tree_services( cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str - ) -> list[dict[str, Any]]: + ) -> list[dict[str,Any]]: """ 获取部门树信息service @@ -30,7 +30,8 @@ class DeptService: :return: 部门树信息对象 """ dept_list_result = await DeptDao.get_dept_list_for_tree(query_db, page_object, data_scope_sql) - dept_tree_result = cls.list_to_tree(dept_list_result) + dept_tree_model_result = cls.list_to_tree(dept_list_result) + dept_tree_result = [dept.model_dump(exclude_unset=True, by_alias=True) for dept in dept_tree_model_result] return dept_tree_result @@ -205,7 +206,7 @@ class DeptService: return result @classmethod - def list_to_tree(cls, permission_list: Sequence[SysDept]) -> list[dict[str, Any]]: + def list_to_tree(cls, permission_list: Sequence[SysDept]) -> list[DeptTreeModel]: """ 工具方法:根据部门列表信息生成树形嵌套数据 @@ -213,25 +214,25 @@ class DeptService: :return: 部门树形嵌套数据 """ _permission_list = [ - {'id': item.dept_id, 'label': item.dept_name, 'parentId': item.parent_id} for item in permission_list + DeptTreeModel(id=item.dept_id, label=item.dept_name, parentId=item.parent_id) for item in permission_list ] # 转成id为key的字典 - mapping: dict[int, dict[str, Any]] = dict(zip([i['id'] for i in _permission_list], _permission_list)) + mapping: dict[int, DeptTreeModel] = dict(zip([i.id for i in _permission_list], _permission_list)) # 树容器 - container: list[dict[str, Any]] = [] + container: list[DeptTreeModel] = [] for d in _permission_list: # 如果找不到父级项,则是根节点 - parent = mapping.get(d['parentId']) + parent = mapping.get(d.parent_id) if parent is None: container.append(d) else: - children: list[dict[str, Any]] = parent.get('children') + children: list[DeptTreeModel] = parent.children if not children: children = [] children.append(d) - parent.update({'children': children}) + parent.children = children return container diff --git a/ruoyi-fastapi-backend/module_admin/service/menu_service.py b/ruoyi-fastapi-backend/module_admin/service/menu_service.py index 1767b69..224e384 100644 --- a/ruoyi-fastapi-backend/module_admin/service/menu_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/menu_service.py @@ -9,7 +9,7 @@ from exceptions.exception import ServiceException, ServiceWarning from module_admin.dao.menu_dao import MenuDao from module_admin.dao.role_dao import RoleDao from module_admin.entity.do.menu_do import SysMenu -from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel +from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel, MenuTreeModel from module_admin.entity.vo.role_vo import RoleMenuQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel from utils.common_util import CamelCaseUtil @@ -35,7 +35,8 @@ class MenuService: menu_list_result = await MenuDao.get_menu_list_for_tree( query_db, current_user.user.user_id, current_user.user.role ) - menu_tree_result = cls.list_to_tree(menu_list_result) + menu_tree_model_result = cls.list_to_tree(menu_list_result) + menu_tree_result = [menu.model_dump(exclude_unset=True, by_alias=True) for menu in menu_tree_model_result] return menu_tree_result @@ -185,7 +186,7 @@ class MenuService: return result @classmethod - def list_to_tree(cls, permission_list: Sequence[SysMenu]) -> list[dict[str, Any]]: + def list_to_tree(cls, permission_list: Sequence[SysMenu]) -> list[MenuTreeModel]: """ 工具方法:根据菜单列表信息生成树形嵌套数据 @@ -193,24 +194,24 @@ class MenuService: :return: 菜单树形嵌套数据 """ _permission_list = [ - {'id': item.menu_id, 'label': item.menu_name, 'parentId': item.parent_id} for item in permission_list + MenuTreeModel(id=item.menu_id, label=item.menu_name, parentId=item.parent_id) for item in permission_list ] # 转成id为key的字典 - mapping: dict[int, dict[str, Any]] = dict(zip([i['id'] for i in _permission_list], _permission_list)) + mapping: dict[int, MenuTreeModel] = dict(zip([i.id for i in _permission_list], _permission_list)) # 树容器 - container: list[dict[str, Any]] = [] + container: list[MenuTreeModel] = [] for d in _permission_list: # 如果找不到父级项,则是根节点 - parent = mapping.get(d['parentId']) + parent = mapping.get(d.parent_id) if parent is None: container.append(d) else: - children: list[dict[str, Any]] = parent.get('children') + children: list[MenuTreeModel] = parent.children if not children: children = [] children.append(d) - parent.update({'children': children}) + parent.children = children return container diff --git a/ruoyi-fastapi-backend/module_admin/service/role_service.py b/ruoyi-fastapi-backend/module_admin/service/role_service.py index c960197..e41c53a 100644 --- a/ruoyi-fastapi-backend/module_admin/service/role_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/role_service.py @@ -318,7 +318,7 @@ class RoleService: query_user_list = await UserDao.get_user_role_allocated_list_by_role_id( query_db, page_object, data_scope_sql, is_page ) - allocated_list = PageModel( + allocated_list = PageModel[UserInfoModel]( **{ **query_user_list.model_dump(by_alias=True), 'rows': [UserInfoModel(**row) for row in query_user_list.rows], @@ -343,7 +343,7 @@ class RoleService: query_user_list = await UserDao.get_user_role_unallocated_list_by_role_id( query_db, page_object, data_scope_sql, is_page ) - unallocated_list = PageModel( + unallocated_list = PageModel[UserInfoModel]( **{ **query_user_list.model_dump(by_alias=True), 'rows': [UserInfoModel(**row) for row in query_user_list.rows], diff --git a/ruoyi-fastapi-backend/module_admin/service/user_service.py b/ruoyi-fastapi-backend/module_admin/service/user_service.py index 9a8bc3c..1d88d03 100644 --- a/ruoyi-fastapi-backend/module_admin/service/user_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/user_service.py @@ -29,6 +29,7 @@ from module_admin.entity.vo.user_vo import ( UserRoleModel, UserRoleQueryModel, UserRoleResponseModel, + UserRowModel, ) from module_admin.service.config_service import ConfigService from module_admin.service.dept_service import DeptService @@ -47,7 +48,7 @@ class UserService: @classmethod async def get_user_list_services( cls, query_db: AsyncSession, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False - ) -> Union[PageModel, list[dict[str, Any]]]: + ) -> Union[PageModel[UserRowModel], list[dict[str, Any]]]: """ 获取用户列表信息service @@ -59,7 +60,7 @@ class UserService: """ query_result = await UserDao.get_user_list(query_db, query_object, data_scope_sql, is_page) if is_page: - user_list_result = PageModel( + user_list_result = PageModel[UserRowModel]( **{ **query_result.model_dump(by_alias=True), 'rows': [{**row[0], 'dept': row[1]} for row in query_result.rows], diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index faab42b..43dd6c4 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -10,10 +11,17 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import RoleInterfaceAuthDependency, UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType -from common.vo import PageResponseModel +from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from config.env import GenConfig from module_admin.entity.vo.user_vo import CurrentUserModel -from module_generator.entity.vo.gen_vo import DeleteGenTableModel, EditGenTableModel, GenTablePageQueryModel +from module_generator.entity.vo.gen_vo import ( + DeleteGenTableModel, + EditGenTableModel, + GenTableDbRowModel, + GenTableDetailModel, + GenTablePageQueryModel, + GenTableRowModel, +) from module_generator.service.gen_service import GenTableColumnService, GenTableService from utils.common_util import bytes2file_response from utils.log_util import logger @@ -24,7 +32,7 @@ gen_controller = APIRouter(prefix='/tool/gen', dependencies=[PreAuthDependency() @gen_controller.get( '/list', - response_model=PageResponseModel, + response_model=PageResponseModel[GenTableRowModel], dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) async def get_gen_table_list( @@ -41,7 +49,7 @@ async def get_gen_table_list( @gen_controller.get( '/db/list', - response_model=PageResponseModel, + response_model=PageResponseModel[GenTableDbRowModel], dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) async def get_gen_db_table_list( @@ -58,6 +66,7 @@ async def get_gen_db_table_list( @gen_controller.post( '/importTable', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:import')], ) @Log(title='代码生成', business_type=BusinessType.IMPORT) @@ -77,6 +86,7 @@ async def import_gen_table( @gen_controller.put( '', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], ) @ValidateFields(validate_model='edit_gen_table') @@ -98,6 +108,7 @@ async def edit_gen_table( @gen_controller.delete( '/{table_ids}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:remove')], ) @Log(title='代码生成', business_type=BusinessType.DELETE) @@ -115,6 +126,7 @@ async def delete_gen_table( @gen_controller.post( '/createTable', + response_model=ResponseBaseModel, dependencies=[RoleInterfaceAuthDependency('admin')], ) @Log(title='创建表', business_type=BusinessType.OTHER) @@ -132,6 +144,15 @@ async def create_table( @gen_controller.get( '/batchGenCode', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回生成的代码文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('tool:gen:code')], ) @Log(title='代码生成', business_type=BusinessType.GENCODE) @@ -149,6 +170,7 @@ async def batch_gen_code( @gen_controller.get( '/genCode/{table_name}', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:code')], ) @Log(title='代码生成', business_type=BusinessType.GENCODE) @@ -168,6 +190,7 @@ async def gen_code_local( @gen_controller.get( '/{table_id}', + response_model=DataResponseModel[GenTableDetailModel], dependencies=[UserInterfaceAuthDependency('tool:gen:query')], ) async def query_detail_gen_table( @@ -186,6 +209,7 @@ async def query_detail_gen_table( @gen_controller.get( '/preview/{table_id}', + response_model=DataResponseModel[dict[str, str]], dependencies=[UserInterfaceAuthDependency('tool:gen:preview')], ) async def preview_code( @@ -201,6 +225,7 @@ async def preview_code( @gen_controller.get( '/synchDb/{table_name}', + response_model=DataResponseModel[str], dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], ) @Log(title='代码生成', business_type=BusinessType.UPDATE) diff --git a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py index c43b227..4e4a67e 100644 --- a/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py +++ b/ruoyi-fastapi-backend/module_generator/entity/vo/gen_vo.py @@ -81,6 +81,27 @@ class GenTableBaseModel(BaseModel): self.get_function_author() +class GenTableRowModel(GenTableBaseModel): + """ + 代码生成业务表行数据模型 + """ + + columns: Optional[list['GenTableColumnBaseModel']] = Field(default=None, description='表列信息') + + +class GenTableDbRowModel(BaseModel): + """ + 代码生成业务表数据库行数据模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + table_name: Optional[str] = Field(default=None, description='表名称') + table_comment: Optional[str] = Field(default=None, description='表描述') + create_time: Optional[datetime] = Field(default=None, description='创建时间') + update_time: Optional[datetime] = Field(default=None, description='更新时间') + + class GenTableModel(GenTableBaseModel): """ 代码生成业务表模型 @@ -145,6 +166,18 @@ class GenTablePageQueryModel(GenTableQueryModel): page_size: int = Field(default=10, description='每页记录数') +class GenTableDetailModel(BaseModel): + """ + 代码生成业务表详情模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + info: Optional[GenTableModel] = Field(default=None, description='业务表信息') + rows: Optional[list['GenTableColumnModel']] = Field(default=None, description='表列信息') + tables: Optional[list['GenTableModel']] = Field(default=None, description='所有业务表信息') + + class DeleteGenTableModel(BaseModel): """ 删除代码生成业务表模型 diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index 56c2dd7..51c44d3 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -14,6 +14,7 @@ from datetime import datetime from typing import Annotated from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -150,6 +151,15 @@ async def query_detail_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.post( '/export', + response_class=StreamingResponse, + responses={ + 200: { + 'description': '流式返回{{ functionName }}列表excel文件', + 'content': { + 'application/octet-stream': {}, + }, + } + }, dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:export')], ) @Log(title='{{ functionName }}', business_type=BusinessType.EXPORT) From 98651f4d8fb4a09cc08d946231617e045bbb1a03 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Mon, 15 Dec 2025 16:18:20 +0800 Subject: [PATCH 21/49] =?UTF-8?q?perf:=20=E6=8E=A5=E5=8F=A3API=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=9A=84=E6=8E=A5=E5=8F=A3=E6=8F=8F=E8=BF=B0=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/cache_controller.py | 19 ++++++++-- .../controller/captcha_controller.py | 2 ++ .../controller/common_controller.py | 6 ++++ .../controller/config_controller.py | 16 +++++++++ .../controller/dept_controller.py | 12 +++++++ .../controller/dict_controller.py | 30 ++++++++++++++++ .../module_admin/controller/job_controller.py | 24 +++++++++++++ .../module_admin/controller/log_controller.py | 18 ++++++++++ .../controller/login_controller.py | 10 ++++++ .../controller/menu_controller.py | 14 ++++++++ .../controller/notice_controller.py | 10 ++++++ .../controller/online_controller.py | 4 +++ .../controller/post_controller.py | 12 +++++++ .../controller/role_controller.py | 28 +++++++++++++++ .../controller/server_controller.py | 2 ++ .../controller/user_controller.py | 36 +++++++++++++++++++ .../controller/gen_controller.py | 22 ++++++++++++ .../templates/python/controller.py.jinja2 | 12 +++++++ 18 files changed, 275 insertions(+), 2 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index 50cb958..12ff29c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -15,6 +15,8 @@ cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[PreAuthDepen @cache_controller.get( '', + summary='获取缓存监控信息接口', + description='用于获取缓存监控信息', response_model=DataResponseModel[CacheMonitorModel], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) @@ -28,6 +30,8 @@ async def get_monitor_cache_info(request: Request) -> Response: @cache_controller.get( '/getNames', + summary='获取缓存名称列表接口', + description='用于获取缓存名称列表', response_model=DataResponseModel[list[CacheInfoModel]], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) @@ -41,6 +45,8 @@ async def get_monitor_cache_name(request: Request) -> Response: @cache_controller.get( '/getKeys/{cache_name}', + summary='获取缓存键列表接口', + description='用于获取指定缓存名称下的所有缓存键列表', response_model=DataResponseModel[list[str]], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) @@ -54,6 +60,8 @@ async def get_monitor_cache_key(request: Request, cache_name: Annotated[str, Pat @cache_controller.get( '/getValue/{cache_name}/{cache_key}', + summary='获取缓存值接口', + description='用于获取指定缓存名称下的指定缓存键对应的值', response_model=DataResponseModel[CacheInfoModel], dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) @@ -71,6 +79,9 @@ async def get_monitor_cache_value( @cache_controller.delete( '/clearCacheName/{cache_name}', + summary='清除缓存名称接口', + description='用于清除指定缓存名称下的所有缓存键值对', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_name( @@ -84,7 +95,9 @@ async def clear_monitor_cache_name( @cache_controller.delete( '/clearCacheKey/{cache_key}', - response_model= ResponseBaseModel, + summary='清除缓存键接口', + description='用于清除指定缓存键对应的值', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Path(description='缓存键')]) -> Response: @@ -96,7 +109,9 @@ async def clear_monitor_cache_key(request: Request, cache_key: Annotated[str, Pa @cache_controller.delete( '/clearCacheAll', - response_model= ResponseBaseModel, + summary='清除所有缓存接口', + description='用于清除所有缓存键值对', + response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:cache:list')], ) async def clear_monitor_cache_all(request: Request) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py index 2eb6358..79bb37c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py @@ -15,6 +15,8 @@ captcha_controller = APIRouter() @captcha_controller.get( '/captchaImage', + summary='获取图片验证码接口', + description='用于获取图片验证码', response_model=DynamicResponseModel[CaptchaCode], ) async def get_captcha_image(request: Request) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py index 182bd8e..f3a041e 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py @@ -15,6 +15,8 @@ common_controller = APIRouter(prefix='/common', dependencies=[PreAuthDependency( @common_controller.post( '/upload', + summary='通用文件上传接口', + description='用于上传文件', response_model=DynamicResponseModel[UploadResponseModel], ) async def common_upload(request: Request, file: Annotated[UploadFile, File(...)]) -> Response: @@ -26,6 +28,8 @@ async def common_upload(request: Request, file: Annotated[UploadFile, File(...)] @common_controller.get( '/download', + summary='通用文件下载接口', + description='用于下载下载目录中的文件', response_class=StreamingResponse, responses={ 200: { @@ -50,6 +54,8 @@ async def common_download( @common_controller.get( '/download/resource', + summary='通用资源文件下载接口', + description='用于下载上传目录中的资源文件', response_class=StreamingResponse, responses={ 200: { diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index 2515cb5..4de4e58 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -24,6 +24,8 @@ config_controller = APIRouter(prefix='/system/config', dependencies=[PreAuthDepe @config_controller.get( '/list', + summary='获取参数分页列表接口', + description='用于获取参数分页列表', response_model=PageResponseModel[ConfigModel], dependencies=[UserInterfaceAuthDependency('system:config:list')], ) @@ -41,6 +43,8 @@ async def get_system_config_list( @config_controller.post( '', + summary='新增参数接口', + description='用于新增参数', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:add')], ) @@ -64,6 +68,8 @@ async def add_system_config( @config_controller.put( '', + summary='编辑参数接口', + description='用于编辑参数', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:edit')], ) @@ -85,6 +91,8 @@ async def edit_system_config( @config_controller.delete( '/refreshCache', + summary='刷新参数缓存接口', + description='用于刷新参数缓存', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:remove')], ) @@ -101,6 +109,8 @@ async def refresh_system_config( @config_controller.delete( '/{config_ids}', + summary='删除参数接口', + description='用于删除参数', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:config:remove')], ) @@ -119,6 +129,8 @@ async def delete_system_config( @config_controller.get( '/{config_id}', + summary='获取参数详情接口', + description='用于获取指定参数的详细信息', response_model=DataResponseModel[ConfigModel], dependencies=[UserInterfaceAuthDependency('system:config:query')], ) @@ -135,6 +147,8 @@ async def query_detail_system_config( @config_controller.get( '/configKey/{config_key}', + summary='根据参数键查询参数值接口', + description='用于根据参数键从缓存中查询参数值', response_model=ResponseBaseModel, ) async def query_system_config(request: Request, config_key: str) -> Response: @@ -147,6 +161,8 @@ async def query_system_config(request: Request, config_key: str) -> Response: @config_controller.post( '/export', + summary='导出参数列表接口', + description='用于导出当前符合查询条件的参数列表数据', response_class=StreamingResponse, responses={ 200: { diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index 8136dcd..ba08921 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -23,6 +23,8 @@ dept_controller = APIRouter(prefix='/system/dept', dependencies=[PreAuthDependen @dept_controller.get( '/list/exclude/{dept_id}', + summary='获取编辑部门的下拉树接口', + description='用于获取部门下拉树,不包含指定部门及其子部门', response_model=DataResponseModel[list[DeptModel]], dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) @@ -41,6 +43,8 @@ async def get_system_dept_tree_for_edit_option( @dept_controller.get( '/list', + summary='获取部门列表接口', + description='用于获取部门列表', response_model=DataResponseModel[list[DeptModel]], dependencies=[UserInterfaceAuthDependency('system:dept:list')], ) @@ -58,6 +62,8 @@ async def get_system_dept_list( @dept_controller.post( '', + summary='新增部门接口', + description='用于新增部门', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:add')], ) @@ -81,6 +87,8 @@ async def add_system_dept( @dept_controller.put( '', + summary='编辑部门接口', + description='用于编辑部门', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:edit')], ) @@ -105,6 +113,8 @@ async def edit_system_dept( @dept_controller.delete( '/{dept_ids}', + summary='删除部门接口', + description='用于删除部门', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dept:remove')], ) @@ -132,6 +142,8 @@ async def delete_system_dept( @dept_controller.get( '/{dept_id}', + summary='获取部门详情接口', + description='用于获取指定部门的详情信息', response_model=DataResponseModel[DeptModel], dependencies=[UserInterfaceAuthDependency('system:dept:query')], ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index d7b9803..793971a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -31,6 +31,8 @@ dict_controller = APIRouter(prefix='/system/dict', dependencies=[PreAuthDependen @dict_controller.get( '/type/list', + summary='获取字典类型分页列表接口', + description='用于获取字典类型分页列表', response_model=PageResponseModel[DictTypeModel], dependencies=[UserInterfaceAuthDependency('system:dict:list')], ) @@ -50,6 +52,8 @@ async def get_system_dict_type_list( @dict_controller.post( '/type', + summary='新增字典类型接口', + description='用于新增字典类型', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:add')], ) @@ -73,6 +77,8 @@ async def add_system_dict_type( @dict_controller.put( '/type', + summary='编辑字典类型接口', + description='用于编辑字典类型', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:edit')], ) @@ -94,6 +100,8 @@ async def edit_system_dict_type( @dict_controller.delete( '/type/refreshCache', + summary='刷新字典缓存接口', + description='用于刷新字典缓存', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:remove')], ) @@ -107,6 +115,8 @@ async def refresh_system_dict(request: Request, query_db: Annotated[AsyncSession @dict_controller.delete( '/type/{dict_ids}', + summary='删除字典类型接口', + description='用于删除字典类型', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:remove')], ) @@ -125,6 +135,8 @@ async def delete_system_dict_type( @dict_controller.get( '/type/optionselect', + summary='获取字典类型下拉列表接口', + description='用于获取字典类型下拉列表', response_model=DataResponseModel[list[DictTypeModel]], ) async def query_system_dict_type_options( @@ -140,6 +152,8 @@ async def query_system_dict_type_options( @dict_controller.get( '/type/{dict_id}', + summary='获取字典类型详情接口', + description='用于获取指定字典类型的详细信息', response_model=DataResponseModel[DictTypeModel], dependencies=[UserInterfaceAuthDependency('system:dict:query')], ) @@ -156,6 +170,8 @@ async def query_detail_system_dict_type( @dict_controller.post( '/type/export', + summary='导出字典类型列表接口', + description='用于导出当前符合查询条件的字典类型列表数据', response_class=StreamingResponse, responses={ 200: { @@ -185,6 +201,8 @@ async def export_system_dict_type_list( @dict_controller.get( '/data/type/{dict_type}', + summary='获取指定字典类型的数据列表接口', + description='用于从缓存中获取指定字典类型的所有数据项', response_model=DataResponseModel[list[DictDataModel]], ) async def query_system_dict_type_data( @@ -203,6 +221,8 @@ async def query_system_dict_type_data( @dict_controller.get( '/data/list', + summary='获取字典数据分页列表接口', + description='用于获取字典数据分页列表', response_model=PageResponseModel[DictDataModel], dependencies=[UserInterfaceAuthDependency('system:dict:list')], ) @@ -222,6 +242,8 @@ async def get_system_dict_data_list( @dict_controller.post( '/data', + summary='新增字典数据接口', + description='用于新增字典数据', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:add')], ) @@ -245,6 +267,8 @@ async def add_system_dict_data( @dict_controller.put( '/data', + summary='编辑字典数据接口', + description='用于编辑字典数据', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:edit')], ) @@ -266,6 +290,8 @@ async def edit_system_dict_data( @dict_controller.delete( '/data/{dict_codes}', + summary='删除字典数据接口', + description='用于删除字典数据', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:dict:remove')], ) @@ -284,6 +310,8 @@ async def delete_system_dict_data( @dict_controller.get( '/data/{dict_code}', + summary='获取字典数据详情接口', + description='用于获取指定字典数据的详细信息', response_model=DataResponseModel[DictDataModel], dependencies=[UserInterfaceAuthDependency('system:dict:query')], ) @@ -300,6 +328,8 @@ async def query_detail_system_dict_data( @dict_controller.post( '/data/export', + summary='导出字典数据列表接口', + description='用于导出当前符合查询条件的字典数据列表数据', response_class=StreamingResponse, responses={ 200: { diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index 33a4bda..e73afc5 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -33,6 +33,8 @@ job_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()] @job_controller.get( '/job/list', + summary='获取定时任务分页列表接口', + description='用于获取定时任务分页列表', response_model=PageResponseModel[JobModel], dependencies=[UserInterfaceAuthDependency('monitor:job:list')], ) @@ -50,6 +52,8 @@ async def get_system_job_list( @job_controller.post( '/job', + summary='新增定时任务接口', + description='用于新增定时任务', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:add')], ) @@ -73,6 +77,8 @@ async def add_system_job( @job_controller.put( '/job', + summary='编辑定时任务接口', + description='用于编辑定时任务', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:edit')], ) @@ -94,6 +100,8 @@ async def edit_system_job( @job_controller.put( '/job/changeStatus', + summary='修改定时任务状态接口', + description='用于修改定时任务状态', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')], ) @@ -119,6 +127,8 @@ async def change_system_job_status( @job_controller.put( '/job/run', + summary='执行定时任务接口', + description='用于执行指定的定时任务', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:changeStatus')], ) @@ -136,6 +146,8 @@ async def execute_system_job( @job_controller.delete( '/job/{job_ids}', + summary='删除定时任务接口', + description='用于删除定时任务', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], ) @@ -154,6 +166,8 @@ async def delete_system_job( @job_controller.get( '/job/{job_id}', + summary='获取定时任务详情接口', + description='用于获取指定定时任务的详情信息', response_model=DataResponseModel[JobModel], dependencies=[UserInterfaceAuthDependency('monitor:job:query')], ) @@ -170,6 +184,8 @@ async def query_detail_system_job( @job_controller.post( '/job/export', + summary='导出定时任务列表接口', + description='用于导出当前符合查询条件的定时任务列表数据', response_class=StreamingResponse, responses={ 200: { @@ -197,6 +213,8 @@ async def export_system_job_list( @job_controller.get( '/jobLog/list', + summary='获取定时任务调度日志分页列表接口', + description='用于获取定时任务调度日志分页列表', response_model=PageResponseModel[JobLogModel], dependencies=[UserInterfaceAuthDependency('monitor:job:list')], ) @@ -216,6 +234,8 @@ async def get_system_job_log_list( @job_controller.delete( '/jobLog/clean', + summary='清空定时任务调度日志接口', + description='用于清空所有定时任务调度日志', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], ) @@ -232,6 +252,8 @@ async def clear_system_job_log( @job_controller.delete( '/jobLog/{job_log_ids}', + summary='删除定时任务调度日志接口', + description='用于删除定时任务调度日志', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:job:remove')], ) @@ -250,6 +272,8 @@ async def delete_system_job_log( @job_controller.post( '/jobLog/export', + summary='导出定时任务调度日志列表接口', + description='用于导出当前符合查询条件的定时任务调度日志列表数据', response_class=StreamingResponse, responses={ 200: { diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index e0a36b4..196abfa 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -29,6 +29,8 @@ log_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()] @log_controller.get( '/operlog/list', + summary='获取操作日志分页列表接口', + description='用于获取操作日志分页列表', response_model=PageResponseModel[OperLogModel], dependencies=[UserInterfaceAuthDependency('monitor:operlog:list')], ) @@ -48,6 +50,8 @@ async def get_system_operation_log_list( @log_controller.delete( '/operlog/clean', + summary='清空操作日志接口', + description='用于清空所有操作日志', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')], ) @@ -63,6 +67,8 @@ async def clear_system_operation_log( @log_controller.delete( '/operlog/{oper_ids}', + summary='删除操作日志接口', + description='用于删除操作日志', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:operlog:remove')], ) @@ -83,6 +89,8 @@ async def delete_system_operation_log( @log_controller.post( '/operlog/export', + summary='导出操作日志接口', + description='用于导出当前符合查询条件的操作日志数据', response_class=StreamingResponse, responses={ 200: { @@ -114,6 +122,8 @@ async def export_system_operation_log_list( @log_controller.get( '/logininfor/list', + summary='获取登录日志分页列表接口', + description='用于获取登录日志分页列表', response_model=PageResponseModel[LogininforModel], dependencies=[UserInterfaceAuthDependency('monitor:logininfor:list')], ) @@ -133,6 +143,8 @@ async def get_system_login_log_list( @log_controller.delete( '/logininfor/clean', + summary='清空登录日志接口', + description='用于清空所有登录日志', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')], ) @@ -148,6 +160,8 @@ async def clear_system_login_log( @log_controller.delete( '/logininfor/{info_ids}', + summary='删除登录日志接口', + description='用于删除登录日志', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:remove')], ) @@ -166,6 +180,8 @@ async def delete_system_login_log( @log_controller.get( '/logininfor/unlock/{user_name}', + summary='解锁账户接口', + description='用于解锁指定用户账户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:logininfor:unlock')], ) @@ -184,6 +200,8 @@ async def unlock_system_user( @log_controller.post( '/logininfor/export', + summary='导出登录日志接口', + description='用于导出当前符合查询条件的登录日志数据', response_class=StreamingResponse, responses={ 200: { diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 7ac208a..5c6c2a9 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -24,6 +24,8 @@ login_controller = APIRouter() @login_controller.post( '/login', + summary='登录接口', + description='用于用户登录', response_model=DynamicResponseModel[Token], ) @Log(title='用户登录', business_type=BusinessType.OTHER, log_type='login') @@ -83,6 +85,8 @@ async def login( @login_controller.get( '/getInfo', + summary='获取用户信息接口', + description='用于获取当前登录用户的信息', response_model=DynamicResponseModel[CurrentUserModel], ) async def get_login_user_info( @@ -95,6 +99,8 @@ async def get_login_user_info( @login_controller.get( '/getRouters', + summary='获取用户路由接口', + description='用于获取当前登录用户的路由信息', response_model=DataResponseModel[list[RouterModel]], ) async def get_login_user_routers( @@ -110,6 +116,8 @@ async def get_login_user_routers( @login_controller.post( '/register', + summary='注册接口', + description='用于用户注册', response_model=DataResponseModel[CrudResponseModel], ) async def register_user( @@ -155,6 +163,8 @@ async def register_user( @login_controller.post( '/logout', + summary='退出登录接口', + description='用于用户退出登录', response_model=ResponseBaseModel, ) async def logout(request: Request, token: Annotated[Optional[str], Depends(oauth2_scheme)]) -> Response: diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index ec97f1b..a9c9b75 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -23,6 +23,8 @@ menu_controller = APIRouter(prefix='/system/menu', dependencies=[PreAuthDependen @menu_controller.get( '/treeselect', + summary='获取菜单树接口', + description='用于获取当前用户可见的菜单树', response_model=DataResponseModel[list[MenuTreeModel]], ) async def get_system_menu_tree( @@ -38,6 +40,8 @@ async def get_system_menu_tree( @menu_controller.get( '/roleMenuTreeselect/{role_id}', + summary='获取角色菜单树接口', + description='用于获取指定角色可见的菜单树', response_model=DynamicResponseModel[RoleMenuQueryModel], ) async def get_system_role_menu_tree( @@ -54,6 +58,8 @@ async def get_system_role_menu_tree( @menu_controller.get( '/list', + summary='获取菜单列表接口', + description='用于获取当前用户可见的菜单列表', response_model=DataResponseModel[list[MenuModel]], dependencies=[UserInterfaceAuthDependency('system:menu:list')], ) @@ -71,6 +77,8 @@ async def get_system_menu_list( @menu_controller.post( '', + summary='新增菜单接口', + description='用于新增菜单', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:add')], ) @@ -94,6 +102,8 @@ async def add_system_menu( @menu_controller.put( '', + summary='编辑菜单接口', + description='用于编辑菜单', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:edit')], ) @@ -115,6 +125,8 @@ async def edit_system_menu( @menu_controller.delete( '/{menu_ids}', + summary='删除菜单接口', + description='用于删除菜单', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:menu:remove')], ) @@ -133,6 +145,8 @@ async def delete_system_menu( @menu_controller.get( '/{menu_id}', + summary='获取菜单详情接口', + description='用于获取指定菜单的详情信息', response_model=DataResponseModel[MenuModel], dependencies=[UserInterfaceAuthDependency('system:menu:query')], ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py index c0351d9..be9cd75 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py @@ -22,6 +22,8 @@ notice_controller = APIRouter(prefix='/system/notice', dependencies=[PreAuthDepe @notice_controller.get( '/list', + summary='获取通知公告分页列表接口', + description='用于获取通知公告分页列表', response_model=PageResponseModel[NoticeModel], dependencies=[UserInterfaceAuthDependency('system:notice:list')], ) @@ -39,6 +41,8 @@ async def get_system_notice_list( @notice_controller.post( '', + summary='新增通知公告接口', + description='用于新增通知公告', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:notice:add')], ) @@ -62,6 +66,8 @@ async def add_system_notice( @notice_controller.put( '', + summary='编辑通知公告接口', + description='用于编辑通知公告', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:notice:edit')], ) @@ -83,6 +89,8 @@ async def edit_system_notice( @notice_controller.delete( '/{notice_ids}', + summary='删除通知公告接口', + description='用于删除通知公告', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:notice:remove')], ) @@ -101,6 +109,8 @@ async def delete_system_notice( @notice_controller.get( '/{notice_id}', + summary='获取通知公告详情接口', + description='用于获取指定通知公告的详细信息', response_model=DataResponseModel[NoticeModel], dependencies=[UserInterfaceAuthDependency('system:notice:query')], ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index 8a01f56..04bfbd7 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -19,6 +19,8 @@ online_controller = APIRouter(prefix='/monitor/online', dependencies=[PreAuthDep @online_controller.get( '/list', + summary='获取在线用户分页列表接口', + description='用于获取在线用户分页列表', response_model=PageResponseModel[OnlineModel], dependencies=[UserInterfaceAuthDependency('monitor:online:list')], ) @@ -37,6 +39,8 @@ async def get_monitor_online_list( @online_controller.delete( '/{token_ids}', + summary='强退在线用户接口', + description='用于强退指定会话编号的在线用户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('monitor:online:forceLogout')], ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index 3ea466c..66b3357 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -24,6 +24,8 @@ post_controller = APIRouter(prefix='/system/post', dependencies=[PreAuthDependen @post_controller.get( '/list', + summary='获取岗位分页列表接口', + description='用于获取岗位分页列表', response_model=PageResponseModel[PostModel], dependencies=[UserInterfaceAuthDependency('system:post:list')], ) @@ -41,6 +43,8 @@ async def get_system_post_list( @post_controller.post( '', + summary='新增岗位接口', + description='用于新增岗位', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:post:add')], ) @@ -64,6 +68,8 @@ async def add_system_post( @post_controller.put( '', + summary='编辑岗位接口', + description='用于编辑岗位', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:post:edit')], ) @@ -85,6 +91,8 @@ async def edit_system_post( @post_controller.delete( '/{post_ids}', + summary='删除岗位接口', + description='用于删除岗位', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:post:remove')], ) @@ -103,6 +111,8 @@ async def delete_system_post( @post_controller.get( '/{post_id}', + summary='获取岗位详情接口', + description='用于获取指定岗位的详细信息', response_model=DataResponseModel[PostModel], dependencies=[UserInterfaceAuthDependency('system:post:query')], ) @@ -119,6 +129,8 @@ async def query_detail_system_post( @post_controller.post( '/export', + summary='导出岗位列表接口', + description='用于导出当前符合查询条件的岗位列表数据', response_class=StreamingResponse, responses={ 200: { diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index 9d3ea2a..907842a 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -34,6 +34,8 @@ role_controller = APIRouter(prefix='/system/role', dependencies=[PreAuthDependen @role_controller.get( '/deptTree/{role_id}', + summary='获取自定义数据权限时可见的部门树接口', + description='用于自定义数据权限时获取当前用户可见的部门树', response_model=DynamicResponseModel[RoleDeptQueryModel], dependencies=[UserInterfaceAuthDependency('system:role:query')], ) @@ -53,6 +55,8 @@ async def get_system_role_dept_tree( @role_controller.get( '/list', + summary='获取角色分页列表接口', + description='用于获取角色分页列表', response_model=PageResponseModel[RoleModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) @@ -72,6 +76,8 @@ async def get_system_role_list( @role_controller.post( '', + summary='新增角色接口', + description='用于新增角色', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:add')], ) @@ -95,6 +101,8 @@ async def add_system_role( @role_controller.put( '', + summary='编辑角色接口', + description='用于编辑角色', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @@ -120,6 +128,8 @@ async def edit_system_role( @role_controller.put( '/dataScope', + summary='编辑角色数据权限接口', + description='用于编辑角色数据权限', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @@ -150,6 +160,8 @@ async def edit_system_role_datascope( @role_controller.delete( '/{role_ids}', + summary='删除角色接口', + description='用于删除角色', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:remove')], ) @@ -176,6 +188,8 @@ async def delete_system_role( @role_controller.get( '/{role_id}', + summary='获取角色详情接口', + description='用于获取指定角色的详细信息', response_model=DataResponseModel[RoleModel], dependencies=[UserInterfaceAuthDependency('system:role:query')], ) @@ -196,6 +210,8 @@ async def query_detail_system_role( @role_controller.post( '/export', + summary='导出角色列表接口', + description='用于导出当前符合查询条件的角色列表数据', response_class=StreamingResponse, responses={ 200: { @@ -226,6 +242,8 @@ async def export_system_role_list( @role_controller.put( '/changeStatus', + summary='修改角色状态接口', + description='用于修改角色状态', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @@ -255,6 +273,8 @@ async def reset_system_role_status( @role_controller.get( '/authUser/allocatedList', + summary='获取已分配用户分页列表接口', + description='用于获取指定角色已分配的用户分页列表', response_model=PageResponseModel[UserInfoModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) @@ -274,6 +294,8 @@ async def get_system_allocated_user_list( @role_controller.get( '/authUser/unallocatedList', + summary='获取未分配用户分页列表接口', + description='用于获取指定角色未分配的用户分页列表', response_model=PageResponseModel[UserInfoModel], dependencies=[UserInterfaceAuthDependency('system:role:list')], ) @@ -293,6 +315,8 @@ async def get_system_unallocated_user_list( @role_controller.put( '/authUser/selectAll', + summary='分配用户给角色接口', + description='用于给指定角色分配用户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @@ -314,6 +338,8 @@ async def add_system_role_user( @role_controller.put( '/authUser/cancel', + summary='取消分配用户给角色接口', + description='用于取消指定用户分配给角色', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) @@ -331,6 +357,8 @@ async def cancel_system_role_user( @role_controller.put( '/authUser/cancelAll', + summary='批量取消分配用户给角色接口', + description='用于批量取消用户分配给角色', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:role:edit')], ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index 0c20659..5c0e705 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -13,6 +13,8 @@ server_controller = APIRouter(prefix='/monitor/server', dependencies=[PreAuthDep @server_controller.get( '', + summary='获取服务器监控信息接口', + description='用于获取当前服务器的监控信息', response_model=DataResponseModel[ServerMonitorModel], dependencies=[UserInterfaceAuthDependency('monitor:server:list')], ) diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index 36467af..50f2235 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -49,6 +49,8 @@ user_controller = APIRouter(prefix='/system/user', dependencies=[PreAuthDependen @user_controller.get( '/deptTree', + summary='获取部门树接口', + description='用于获取当前登录用户可见的部门树', response_model=DataResponseModel[list[DeptTreeModel]], dependencies=[UserInterfaceAuthDependency('system:user:list')], ) @@ -65,6 +67,8 @@ async def get_system_dept_tree( @user_controller.get( '/list', + summary='获取用户分页列表接口', + description='用于获取用户分页列表', response_model=PageResponseModel[UserRowModel], dependencies=[UserInterfaceAuthDependency('system:user:list')], ) @@ -85,6 +89,8 @@ async def get_system_user_list( @user_controller.post( '', + summary='新增用户接口', + description='用于新增用户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:add')], ) @@ -116,6 +122,8 @@ async def add_system_user( @user_controller.put( '', + summary='编辑用户接口', + description='用于编辑用户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) @@ -147,6 +155,8 @@ async def edit_system_user( @user_controller.delete( '/{user_ids}', + summary='删除用户接口', + description='用于删除用户', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:remove')], ) @@ -177,6 +187,8 @@ async def delete_system_user( @user_controller.put( '/resetPwd', + summary='重置用户密码接口', + description='用于重置用户密码', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:resetPwd')], ) @@ -207,6 +219,8 @@ async def reset_system_user_pwd( @user_controller.put( '/changeStatus', + summary='修改用户状态接口', + description='用于修改用户状态', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) @@ -236,6 +250,8 @@ async def change_system_user_status( @user_controller.get( '/profile', + summary='获取用户个人信息接口', + description='用于获取当前登录用户的个人信息', response_model=DynamicResponseModel[UserProfileModel], ) async def query_detail_system_user_profile( @@ -251,11 +267,15 @@ async def query_detail_system_user_profile( @user_controller.get( '/{user_id}', + summary='获取用户详情接口', + description='用于获取指定用户的详情信息', response_model=DynamicResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @user_controller.get( '/', + summary='获取用户岗位和角色列表接口', + description='用于获取当前登录用户可见的岗位和角色列表', response_model=DynamicResponseModel[UserDetailModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @@ -276,6 +296,8 @@ async def query_detail_system_user( @user_controller.post( '/profile/avatar', + summary='修改用户头像接口', + description='用于修改当前登录用户的头像', response_model=DynamicResponseModel[AvatarModel], ) @Log(title='个人信息', business_type=BusinessType.UPDATE) @@ -314,6 +336,8 @@ async def change_system_user_profile_avatar( @user_controller.put( '/profile', + summary='修改用户个人信息接口', + description='用于修改当前登录用户的个人信息', response_model=ResponseBaseModel, ) @Log(title='个人信息', business_type=BusinessType.UPDATE) @@ -341,6 +365,8 @@ async def change_system_user_profile_info( @user_controller.put( '/profile/updatePwd', + summary='修改用户密码接口', + description='用于修改当前登录用户的密码', response_model=ResponseBaseModel, ) @Log(title='个人信息', business_type=BusinessType.UPDATE) @@ -366,6 +392,8 @@ async def reset_system_user_password( @user_controller.post( '/importData', + summary='批量导入用户接口', + description='用于批量导入用户数据', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:import')], ) @@ -389,6 +417,8 @@ async def batch_import_system_user( @user_controller.post( '/importTemplate', + summary='获取用户导入模板接口', + description='用于获取用户导入模板excel文件', response_class=StreamingResponse, responses={ 200: { @@ -411,6 +441,8 @@ async def export_system_user_template( @user_controller.post( '/export', + summary='导出用户列表接口', + description='用于导出当前符合查询条件的用户列表数据', response_class=StreamingResponse, responses={ 200: { @@ -441,6 +473,8 @@ async def export_system_user_list( @user_controller.get( '/authRole/{user_id}', + summary='获取用户已分配角色列表接口', + description='用于获取指定用户已分配的角色列表', response_model=DynamicResponseModel[UserRoleResponseModel], dependencies=[UserInterfaceAuthDependency('system:user:query')], ) @@ -460,6 +494,8 @@ async def get_system_allocated_role_list( @user_controller.put( '/authRole', + summary='给用户分配角色接口', + description='用于给指定用户分配角色', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('system:user:edit')], ) diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index 43dd6c4..da2a753 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -32,6 +32,8 @@ gen_controller = APIRouter(prefix='/tool/gen', dependencies=[PreAuthDependency() @gen_controller.get( '/list', + summary='获取代码生成表分页列表接口', + description='用于获取代码生成表分页列表', response_model=PageResponseModel[GenTableRowModel], dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) @@ -49,6 +51,8 @@ async def get_gen_table_list( @gen_controller.get( '/db/list', + summary='获取数据库表分页列表接口', + description='用于获取数据库表分页列表', response_model=PageResponseModel[GenTableDbRowModel], dependencies=[UserInterfaceAuthDependency('tool:gen:list')], ) @@ -66,6 +70,8 @@ async def get_gen_db_table_list( @gen_controller.post( '/importTable', + summary='导入数据库表接口', + description='用于导入数据库表', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:import')], ) @@ -86,6 +92,8 @@ async def import_gen_table( @gen_controller.put( '', + summary='编辑代码生成表接口', + description='用于编辑代码生成表', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], ) @@ -108,6 +116,8 @@ async def edit_gen_table( @gen_controller.delete( '/{table_ids}', + summary='删除代码生成表接口', + description='用于删除代码生成表', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:remove')], ) @@ -126,6 +136,8 @@ async def delete_gen_table( @gen_controller.post( '/createTable', + summary='创建数据库表接口', + description='用于创建数据库表', response_model=ResponseBaseModel, dependencies=[RoleInterfaceAuthDependency('admin')], ) @@ -144,6 +156,8 @@ async def create_table( @gen_controller.get( '/batchGenCode', + summary='生成代码文件接口', + description='用于生成代码文件', response_class=StreamingResponse, responses={ 200: { @@ -170,6 +184,8 @@ async def batch_gen_code( @gen_controller.get( '/genCode/{table_name}', + summary='生成代码文件到本地接口', + description='用于生成代码文件到本地', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('tool:gen:code')], ) @@ -190,6 +206,8 @@ async def gen_code_local( @gen_controller.get( '/{table_id}', + summary='获取代码生成表详情接口', + description='用于获取指定代码生成表的详细信息', response_model=DataResponseModel[GenTableDetailModel], dependencies=[UserInterfaceAuthDependency('tool:gen:query')], ) @@ -209,6 +227,8 @@ async def query_detail_gen_table( @gen_controller.get( '/preview/{table_id}', + summary='预览生成的代码接口', + description='用于预览指定代码生成表生成的代码', response_model=DataResponseModel[dict[str, str]], dependencies=[UserInterfaceAuthDependency('tool:gen:preview')], ) @@ -225,6 +245,8 @@ async def preview_code( @gen_controller.get( '/synchDb/{table_name}', + summary='同步数据库接口', + description='用于同步指定数据库信息到指定代码生成表', response_model=DataResponseModel[str], dependencies=[UserInterfaceAuthDependency('tool:gen:edit')], ) diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index 51c44d3..e47e5cc 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -37,6 +37,8 @@ from utils.response_util import ResponseUtil @{{ businessName }}_controller.get( '/list', + summary='获取{{ functionName }}分页列表接口', + description='用于获取{{ functionName }}分页列表', response_model=PageResponseModel[{{ BusinessName }}Model], dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:list')], ) @@ -61,6 +63,8 @@ async def get_{{ moduleName }}_{{ businessName }}_list( @{{ businessName }}_controller.post( '', + summary='新增{{ functionName }}接口', + description='用于新增{{ functionName }}', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:add')], ) @@ -91,6 +95,8 @@ async def add_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.put( '', + summary='编辑{{ functionName }}接口', + description='用于编辑{{ functionName }}', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:edit')], ) @@ -117,6 +123,8 @@ async def edit_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.delete( '/{% raw %}{{% endraw %}{{ pk_field }}s{% raw %}}{% endraw %}', + summary='删除{{ functionName }}接口', + description='用于删除{{ functionName }}', response_model=ResponseBaseModel, dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:remove')], ) @@ -135,6 +143,8 @@ async def delete_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.get( '/{% raw %}{{% endraw %}{{ pk_field }}{% raw %}}{% endraw %}', + summary='获取{{ functionName }}详情接口', + description='用于获取指定{{ functionName }}的详细信息', response_model=DataResponseModel[{{ BusinessName }}Model], dependencies=[UserInterfaceAuthDependency('{{ permissionPrefix }}:query')] ) @@ -151,6 +161,8 @@ async def query_detail_{{ moduleName }}_{{ businessName }}( @{{ businessName }}_controller.post( '/export', + summary='导出{{ functionName }}列表接口', + description='用于导出当前符合查询条件的{{ functionName }}列表数据', response_class=StreamingResponse, responses={ 200: { From d36439457580effcfea4c4941f06933728c46157 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Mon, 15 Dec 2025 16:49:30 +0800 Subject: [PATCH 22/49] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=A3=81?= =?UTF-8?q?=E7=9B=98=E5=AD=98=E5=9C=A8=E5=BC=82=E5=B8=B8=E6=97=B6=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=9B=91=E6=8E=A7=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_admin/service/server_service.py | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/service/server_service.py b/ruoyi-fastapi-backend/module_admin/service/server_service.py index 7bfca70..5a39698 100644 --- a/ruoyi-fastapi-backend/module_admin/service/server_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/server_service.py @@ -81,17 +81,21 @@ class ServerService: io = psutil.disk_partitions() sys_files = [] for i in io: - o = psutil.disk_usage(i.device) - disk_data = SysFiles( - dirName=i.device, - sysTypeName=i.fstype, - typeName='本地固定磁盘(' + i.mountpoint.replace('\\', '') + ')', - total=bytes2human(o.total), - used=bytes2human(o.used), - free=bytes2human(o.free), - usage=f'{psutil.disk_usage(i.device).percent}%', - ) - sys_files.append(disk_data) + try: + o = psutil.disk_usage(i.device) + disk_data = SysFiles( + dirName=i.device, + sysTypeName=i.fstype, + typeName='本地固定磁盘(' + i.mountpoint.replace('\\', '') + ')', + total=bytes2human(o.total), + used=bytes2human(o.used), + free=bytes2human(o.free), + usage=f'{psutil.disk_usage(i.device).percent}%', + ) + sys_files.append(disk_data) + except Exception: # noqa: PERF203 + # 忽略所有异常,跳过有问题的磁盘 + continue result = ServerMonitorModel(cpu=cpu, mem=mem, sys=sys, py=py, sysFiles=sys_files) From 50af1bf573b544afafa9352409171e26d5bbd952 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Mon, 15 Dec 2025 17:08:43 +0800 Subject: [PATCH 23/49] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=9C=A8?= =?UTF-8?q?=E7=BA=BF=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8=E4=B8=8EPageRespo?= =?UTF-8?q?nseModel=E4=B8=8D=E5=85=BC=E5=AE=B9=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_admin/controller/online_controller.py | 8 ++++---- .../module_admin/entity/vo/online_vo.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index 04bfbd7..7a2299f 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -8,8 +8,8 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType -from common.vo import PageResponseModel, ResponseBaseModel -from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlineModel, OnlineQueryModel +from common.vo import ResponseBaseModel +from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlinePageResponseModel, OnlineQueryModel from module_admin.service.online_service import OnlineService from utils.log_util import logger from utils.response_util import ResponseUtil @@ -21,7 +21,7 @@ online_controller = APIRouter(prefix='/monitor/online', dependencies=[PreAuthDep '/list', summary='获取在线用户分页列表接口', description='用于获取在线用户分页列表', - response_model=PageResponseModel[OnlineModel], + response_model=OnlinePageResponseModel, dependencies=[UserInterfaceAuthDependency('monitor:online:list')], ) async def get_monitor_online_list( @@ -33,7 +33,7 @@ async def get_monitor_online_list( logger.info('获取成功') return ResponseUtil.success( - model_content=PageResponseModel(rows=online_query_result, total=len(online_query_result)) + model_content=OnlinePageResponseModel(rows=online_query_result, total=len(online_query_result)) ) diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py index 68eda31..074b1bb 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/online_vo.py @@ -31,6 +31,17 @@ class OnlineQueryModel(OnlineModel): end_time: Optional[str] = Field(default=None, description='结束时间') +class OnlinePageResponseModel(BaseModel): + """ + 在线用户分页响应模型 + """ + + model_config = ConfigDict(alias_generator=to_camel) + + rows: list[OnlineModel] = Field(description='在线用户记录列表') + total: int = Field(description='总记录数') + + class DeleteOnlineModel(BaseModel): """ 强退在线用户模型 From ad0327bf51d61830344d581ef57e2bca2336d4e0 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Tue, 16 Dec 2025 14:38:31 +0800 Subject: [PATCH 24/49] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84app?= =?UTF-8?q?=E4=B8=8Eserver=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/app.py | 5 +- ruoyi-fastapi-backend/server.py | 87 ++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/ruoyi-fastapi-backend/app.py b/ruoyi-fastapi-backend/app.py index 9c7e7d5..2d2072d 100644 --- a/ruoyi-fastapi-backend/app.py +++ b/ruoyi-fastapi-backend/app.py @@ -1,6 +1,9 @@ import uvicorn -from server import AppConfig, app # noqa: F401 +from config.env import AppConfig +from server import create_app + +app = create_app() if __name__ == '__main__': uvicorn.run( diff --git a/ruoyi-fastapi-backend/server.py b/ruoyi-fastapi-backend/server.py index d401110..3dbade1 100644 --- a/ruoyi-fastapi-backend/server.py +++ b/ruoyi-fastapi-backend/server.py @@ -47,42 +47,59 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: await SchedulerUtil.close_system_scheduler() -# 初始化FastAPI对象 -app = FastAPI( - title=AppConfig.app_name, - description=f'{AppConfig.app_name}接口文档', - version=AppConfig.app_version, - lifespan=lifespan, -) +def register_routers(app: FastAPI) -> None: + """ + 注册路由 -# 挂载子应用 -handle_sub_applications(app) -# 加载中间件处理方法 -handle_middleware(app) -# 加载全局异常处理方法 -handle_exception(app) + :param app: FastAPI对象 + :return: + """ + # 加载路由列表 + controller_list = [ + {'router': login_controller, 'tags': ['登录模块']}, + {'router': captcha_controller, 'tags': ['验证码模块']}, + {'router': user_controller, 'tags': ['系统管理-用户管理']}, + {'router': role_controller, 'tags': ['系统管理-角色管理']}, + {'router': menu_controller, 'tags': ['系统管理-菜单管理']}, + {'router': dept_controller, 'tags': ['系统管理-部门管理']}, + {'router': post_controller, 'tags': ['系统管理-岗位管理']}, + {'router': dict_controller, 'tags': ['系统管理-字典管理']}, + {'router': config_controller, 'tags': ['系统管理-参数管理']}, + {'router': notice_controller, 'tags': ['系统管理-通知公告管理']}, + {'router': log_controller, 'tags': ['系统管理-日志管理']}, + {'router': online_controller, 'tags': ['系统监控-在线用户']}, + {'router': job_controller, 'tags': ['系统监控-定时任务']}, + {'router': server_controller, 'tags': ['系统监控-服务监控']}, + {'router': cache_controller, 'tags': ['系统监控-缓存监控']}, + {'router': common_controller, 'tags': ['通用模块']}, + {'router': gen_controller, 'tags': ['代码生成']}, + ] + + for controller in controller_list: + app.include_router(router=controller.get('router'), tags=controller.get('tags')) -# 加载路由列表 -controller_list = [ - {'router': login_controller, 'tags': ['登录模块']}, - {'router': captcha_controller, 'tags': ['验证码模块']}, - {'router': user_controller, 'tags': ['系统管理-用户管理']}, - {'router': role_controller, 'tags': ['系统管理-角色管理']}, - {'router': menu_controller, 'tags': ['系统管理-菜单管理']}, - {'router': dept_controller, 'tags': ['系统管理-部门管理']}, - {'router': post_controller, 'tags': ['系统管理-岗位管理']}, - {'router': dict_controller, 'tags': ['系统管理-字典管理']}, - {'router': config_controller, 'tags': ['系统管理-参数管理']}, - {'router': notice_controller, 'tags': ['系统管理-通知公告管理']}, - {'router': log_controller, 'tags': ['系统管理-日志管理']}, - {'router': online_controller, 'tags': ['系统监控-在线用户']}, - {'router': job_controller, 'tags': ['系统监控-定时任务']}, - {'router': server_controller, 'tags': ['系统监控-服务监控']}, - {'router': cache_controller, 'tags': ['系统监控-缓存监控']}, - {'router': common_controller, 'tags': ['通用模块']}, - {'router': gen_controller, 'tags': ['代码生成']}, -] +def create_app() -> FastAPI: + """ + 创建FastAPI应用 -for controller in controller_list: - app.include_router(router=controller.get('router'), tags=controller.get('tags')) + :return: FastAPI对象 + """ + # 初始化FastAPI对象 + app = FastAPI( + title=AppConfig.app_name, + description=f'{AppConfig.app_name}接口文档', + version=AppConfig.app_version, + lifespan=lifespan, + ) + + # 挂载子应用 + handle_sub_applications(app) + # 加载中间件处理方法 + handle_middleware(app) + # 加载全局异常处理方法 + handle_exception(app) + # 注册路由 + register_routers(app) + + return app From cdacb1643c76da2f41d873ef7fa372dabe9ab36f Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Tue, 16 Dec 2025 16:15:52 +0800 Subject: [PATCH 25/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E6=A1=A3=E9=9D=99=E6=80=81=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/server.py | 45 ++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/ruoyi-fastapi-backend/server.py b/ruoyi-fastapi-backend/server.py index 3dbade1..bb2fbe7 100644 --- a/ruoyi-fastapi-backend/server.py +++ b/ruoyi-fastapi-backend/server.py @@ -1,7 +1,9 @@ from collections.abc import AsyncGenerator from contextlib import asynccontextmanager -from fastapi import FastAPI +from fastapi import FastAPI, applications +from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html +from fastapi.responses import HTMLResponse from config.env import AppConfig from config.get_db import init_create_table @@ -47,6 +49,45 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: await SchedulerUtil.close_system_scheduler() +def setup_docs_static_resources( + redoc_js_url: str = 'https://registry.npmmirror.com/redoc/2/files/bundles/redoc.standalone.js', + redoc_favicon_url: str = 'https://fastapi.tiangolo.com/img/favicon.png', + swagger_js_url: str = 'https://registry.npmmirror.com/swagger-ui-dist/5/files/swagger-ui-bundle.js', + swagger_css_url: str = 'https://registry.npmmirror.com/swagger-ui-dist/5/files/swagger-ui.css', + swagger_favicon_url: str = 'https://fastapi.tiangolo.com/img/favicon.png', +) -> None: + """ + 配置文档静态资源 + + :param redoc_js_url: 用于加载ReDoc JavaScript的URL + :param redoc_favicon_url: ReDoc要使用的favicon的URL + :param swagger_js_url: 用于加载Swagger UI JavaScript的URL + :param swagger_css_url: 用于加载Swagger UI CSS的URL + :param swagger_favicon_url: Swagger UI要使用的favicon的URL + :return: + """ + + def redoc_monkey_patch(*args, **kwargs) -> HTMLResponse: + return get_redoc_html( + *args, + **kwargs, + redoc_js_url=redoc_js_url, + redoc_favicon_url=redoc_favicon_url, + ) + + def swagger_ui_monkey_patch(*args, **kwargs) -> HTMLResponse: + return get_swagger_ui_html( + *args, + **kwargs, + swagger_js_url=swagger_js_url, + swagger_css_url=swagger_css_url, + swagger_favicon_url=swagger_favicon_url, + ) + + applications.get_redoc_html = redoc_monkey_patch + applications.get_swagger_ui_html = swagger_ui_monkey_patch + + def register_routers(app: FastAPI) -> None: """ 注册路由 @@ -85,6 +126,8 @@ def create_app() -> FastAPI: :return: FastAPI对象 """ + # 配置文档静态资源 + setup_docs_static_resources() # 初始化FastAPI对象 app = FastAPI( title=AppConfig.app_name, From a28922acf0192760268cf4ed102a7a8f9e3e8218 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Wed, 17 Dec 2025 15:51:36 +0800 Subject: [PATCH 26/49] =?UTF-8?q?style:=20=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/module_admin/service/dept_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-fastapi-backend/module_admin/service/dept_service.py b/ruoyi-fastapi-backend/module_admin/service/dept_service.py index b939c41..c9c9a19 100644 --- a/ruoyi-fastapi-backend/module_admin/service/dept_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/dept_service.py @@ -20,7 +20,7 @@ class DeptService: @classmethod async def get_dept_tree_services( cls, query_db: AsyncSession, page_object: DeptModel, data_scope_sql: str - ) -> list[dict[str,Any]]: + ) -> list[dict[str, Any]]: """ 获取部门树信息service From 1857663c9ffb185fa8ae04ed28efb99ecdc80d76 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Wed, 17 Dec 2025 15:52:22 +0800 Subject: [PATCH 27/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=B3=A8=E5=86=8C=E8=B7=AF=E7=94=B1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/common/router.py | 405 ++++++++++++++++++ .../controller/cache_controller.py | 7 +- .../controller/captcha_controller.py | 5 +- .../controller/common_controller.py | 5 +- .../controller/config_controller.py | 7 +- .../controller/dept_controller.py | 7 +- .../controller/dict_controller.py | 7 +- .../module_admin/controller/job_controller.py | 7 +- .../module_admin/controller/log_controller.py | 7 +- .../controller/login_controller.py | 5 +- .../controller/menu_controller.py | 7 +- .../controller/notice_controller.py | 7 +- .../controller/online_controller.py | 7 +- .../controller/post_controller.py | 7 +- .../controller/role_controller.py | 7 +- .../controller/server_controller.py | 7 +- .../controller/user_controller.py | 7 +- .../controller/gen_controller.py | 5 +- ruoyi-fastapi-backend/server.py | 54 +-- 19 files changed, 485 insertions(+), 85 deletions(-) create mode 100644 ruoyi-fastapi-backend/common/router.py diff --git a/ruoyi-fastapi-backend/common/router.py b/ruoyi-fastapi-backend/common/router.py new file mode 100644 index 0000000..5e413cd --- /dev/null +++ b/ruoyi-fastapi-backend/common/router.py @@ -0,0 +1,405 @@ +import importlib +import os +import sys +from collections.abc import Sequence +from enum import Enum +from typing import Annotated, Any, Callable, Literal, Optional, Union + +from annotated_doc import Doc +from fastapi import FastAPI, params +from fastapi.datastructures import Default +from fastapi.routing import APIRoute, APIRouter +from fastapi.utils import generate_unique_id +from starlette.responses import JSONResponse, Response +from starlette.routing import BaseRoute +from starlette.types import ASGIApp, Lifespan +from typing_extensions import deprecated + + +class APIRouterPro(APIRouter): + """ + `APIRouterPro` class, inherited from the `APIRouter` class, it has all the functions of `APIRouter` and provides some additional parameter settings. + `APIRouter` class, used to group *path operations*, for example to structure + an app in multiple files. It would then be included in the `FastAPI` app, or + in another `APIRouter` (ultimately included in the app). + + Read more about it in the + [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/). + + ## Example + + ```python + from common.router import APIRouterPro, FastAPI + + app = FastAPI() + router = APIRouterPro() + + + @router.get('/users/', tags=['users']) + async def read_users(): + return [{'username': 'Rick'}, {'username': 'Morty'}] + + + app.include_router(router) + ``` + """ + + def __init__( # noqa: PLR0913 + self, + *, + prefix: Annotated[str, Doc('An optional path prefix for the router.')] = '', + order_num: Annotated[int, Doc('An optional order number for the router.')] = 100, + auto_register: Annotated[bool, Doc('An optional auto register flag for the router.')] = True, + tags: Annotated[ + Optional[list[Union[str, Enum]]], + Doc( + """ + A list of tags to be applied to all the *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + dependencies: Annotated[ + Optional[Sequence[params.Depends]], + Doc( + """ + A list of dependencies (using `Depends()`) to be applied to all the + *path operations* in this router. + + Read more about it in the + [FastAPI docs for Bigger Applications - Multiple Files](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + default_response_class: Annotated[ + type[Response], + Doc( + """ + The default response class to be used. + + Read more in the + [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). + """ + ), + ] = Default(JSONResponse), + responses: Annotated[ + Optional[dict[Union[int, str], dict[str, Any]]], + Doc( + """ + Additional responses to be shown in OpenAPI. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Additional Responses in OpenAPI](https://fastapi.tiangolo.com/advanced/additional-responses/). + + And in the + [FastAPI docs for Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies). + """ + ), + ] = None, + callbacks: Annotated[ + Optional[list[BaseRoute]], + Doc( + """ + OpenAPI callbacks that should apply to all *path operations* in this + router. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for OpenAPI Callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/). + """ + ), + ] = None, + routes: Annotated[ + Optional[list[BaseRoute]], + Doc( + """ + **Note**: you probably shouldn't use this parameter, it is inherited + from Starlette and supported for compatibility. + + --- + + A list of routes to serve incoming HTTP and WebSocket requests. + """ + ), + deprecated( + """ + You normally wouldn't use this parameter with FastAPI, it is inherited + from Starlette and supported for compatibility. + + In FastAPI, you normally would use the *path operation methods*, + like `router.get()`, `router.post()`, etc. + """ + ), + ] = None, + redirect_slashes: Annotated[ + bool, + Doc( + """ + Whether to detect and redirect slashes in URLs when the client doesn't + use the same format. + """ + ), + ] = True, + default: Annotated[ + Optional[ASGIApp], + Doc( + """ + Default function handler for this router. Used to handle + 404 Not Found errors. + """ + ), + ] = None, + dependency_overrides_provider: Annotated[ + Optional[Any], + Doc( + """ + Only used internally by FastAPI to handle dependency overrides. + + You shouldn't need to use it. It normally points to the `FastAPI` app + object. + """ + ), + ] = None, + route_class: Annotated[ + type[APIRoute], + Doc( + """ + Custom route (*path operation*) class to be used by this router. + + Read more about it in the + [FastAPI docs for Custom Request and APIRoute class](https://fastapi.tiangolo.com/how-to/custom-request-and-route/#custom-apiroute-class-in-a-router). + """ + ), + ] = APIRoute, + on_startup: Annotated[ + Optional[Sequence[Callable[[], Any]]], + Doc( + """ + A list of startup event handler functions. + + You should instead use the `lifespan` handlers. + + Read more in the [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + on_shutdown: Annotated[ + Optional[Sequence[Callable[[], Any]]], + Doc( + """ + A list of shutdown event handler functions. + + You should instead use the `lifespan` handlers. + + Read more in the + [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + # the generic to Lifespan[AppType] is the type of the top level application + # which the router cannot know statically, so we use typing.Any + lifespan: Annotated[ + Optional[Lifespan[Any]], + Doc( + """ + A `Lifespan` context manager handler. This replaces `startup` and + `shutdown` functions with a single context manager. + + Read more in the + [FastAPI docs for `lifespan`](https://fastapi.tiangolo.com/advanced/events/). + """ + ), + ] = None, + deprecated: Annotated[ + Optional[bool], + Doc( + """ + Mark all *path operations* in this router as deprecated. + + It will be added to the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Path Operation Configuration](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/). + """ + ), + ] = None, + include_in_schema: Annotated[ + bool, + Doc( + """ + To include (or not) all the *path operations* in this router in the + generated OpenAPI. + + This affects the generated OpenAPI (e.g. visible at `/docs`). + + Read more about it in the + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). + """ + ), + ] = True, + generate_unique_id_function: Annotated[ + Callable[[APIRoute], str], + Doc( + """ + Customize the function used to generate unique IDs for the *path + operations* shown in the generated OpenAPI. + + This is particularly useful when automatically generating clients or + SDKs for your API. + + Read more about it in the + [FastAPI docs about how to Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/#custom-generate-unique-id-function). + """ + ), + ] = Default(generate_unique_id), + ) -> None: + self.order_num = order_num + self.auto_register = auto_register + super().__init__( + prefix=prefix, + tags=tags, + dependencies=dependencies, + default_response_class=default_response_class, + responses=responses, + callbacks=callbacks, + routes=routes, + redirect_slashes=redirect_slashes, + default=default, + dependency_overrides_provider=dependency_overrides_provider, + route_class=route_class, + on_startup=on_startup, + on_shutdown=on_shutdown, + lifespan=lifespan, + deprecated=deprecated, + include_in_schema=include_in_schema, + generate_unique_id_function=generate_unique_id_function, + ) + + +class RouterRegister: + """ + 路由注册器,用于自动注册所有controller目录下的路由 + """ + + def __init__(self, app: FastAPI) -> None: + """ + 初始化路由注册器 + + :param app: FastAPI对象 + """ + self.app = app + # 获取项目根目录 + self.project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + sys.path.insert(0, self.project_root) + + def _find_controller_files(self) -> list[str]: + """ + 查找所有controller目录下的py文件 + + :return: py文件路径列表 + """ + controller_files = [] + # 遍历所有目录,查找controller目录 + for root, _dirs, files in os.walk(self.project_root): + # 检查当前目录是否为controller目录 + if os.path.basename(root) == 'controller': + # 遍历controller目录下的所有py文件 + for file in files: + if file.endswith('.py') and not file.startswith('__'): + file_path = os.path.join(root, file) + controller_files.append(file_path) + return controller_files + + def _import_module_and_get_routers(self, controller_files: list[str]) -> list[tuple[str, APIRouter]]: + """ + 导入模块并获取路由实例 + + :param controller_files: controller目录下的py文件路径列表 + :return: 路由实例列表 + """ + routers = [] + for file_path in controller_files: + # 计算模块路径 + relative_path = os.path.relpath(file_path, self.project_root) + module_name = relative_path.replace(os.sep, '.')[:-3] + + try: + # 动态导入模块 + module = importlib.import_module(module_name) + # 遍历模块属性,寻找APIRouter和APIRouterPro实例 + for attr_name in dir(module): + attr = getattr(module, attr_name) + # 对于APIRouterPro实例,只有当auto_register=True时才添加 + if isinstance(attr, APIRouterPro): + if attr.auto_register: + routers.append((attr_name, attr)) + # 对于APIRouter实例,直接添加 + elif isinstance(attr, APIRouter): + routers.append((attr_name, attr)) + except Exception as e: + print(f'Error importing module {module_name}: {e}') + return routers + + def _sort_routers(self, routers: list[tuple[str, APIRouter]]) -> list[tuple[str, APIRouter]]: + """ + 按规则排序路由 + + :param routers: 路由实例列表 + :return: 排序后的路由实例列表 + """ + + # 按规则排序路由 + def sort_key(item: tuple[str, APIRouter]) -> Union[tuple[Literal[0], int, str], tuple[Literal[1], str]]: + attr_name, router = item + # APIRouterPro实例按order_num排序,序号越小越靠前 + if isinstance(router, APIRouterPro): + return (0, router.order_num, attr_name) + # APIRouter实例按变量名首字母排序 + return (1, attr_name) + + return sorted(routers, key=sort_key) + + def _register_routers_to_app(self, routers: list[tuple[str, APIRouter]]) -> None: + """ + 将路由注册到FastAPI应用 + + :param routers: 排序后的路由实例列表 + :return: None + """ + for _attr_name, router in routers: + self.app.include_router(router=router) + + def register_routers(self) -> None: + """ + 自动注册所有controller目录下的路由 + + :return: None + """ + # 查找所有controller目录下的py文件 + controller_files = self._find_controller_files() + # 导入模块并获取路由实例 + routers = self._import_module_and_get_routers(controller_files) + # 按规则排序路由 + sorted_routers = self._sort_routers(routers) + # 注册路由到FastAPI应用 + self._register_routers_to_app(sorted_routers) + + +def auto_register_routers(app: FastAPI) -> None: + """ + 自动注册所有controller目录下的路由 + + :param app: FastAPI对象 + :return: None + """ + # 使用路由注册器进行注册 + router_register = RouterRegister(app) + router_register.register_routers() diff --git a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py index 12ff29c..e1f04e3 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/cache_controller.py @@ -1,16 +1,19 @@ from typing import Annotated -from fastapi import APIRouter, Path, Request, Response +from fastapi import Path, Request, Response from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency +from common.router import APIRouterPro from common.vo import DataResponseModel, ResponseBaseModel from module_admin.entity.vo.cache_vo import CacheInfoModel, CacheMonitorModel from module_admin.service.cache_service import CacheService from utils.log_util import logger from utils.response_util import ResponseUtil -cache_controller = APIRouter(prefix='/monitor/cache', dependencies=[PreAuthDependency()]) +cache_controller = APIRouterPro( + prefix='/monitor/cache', order_num=15, tags=['系统监控-缓存监控'], dependencies=[PreAuthDependency()] +) @cache_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py index 79bb37c..e7f6cb5 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/captcha_controller.py @@ -1,16 +1,17 @@ import uuid from datetime import timedelta -from fastapi import APIRouter, Request, Response +from fastapi import Request, Response from common.enums import RedisInitKeyConfig +from common.router import APIRouterPro from common.vo import DynamicResponseModel from module_admin.entity.vo.login_vo import CaptchaCode from module_admin.service.captcha_service import CaptchaService from utils.log_util import logger from utils.response_util import ResponseUtil -captcha_controller = APIRouter() +captcha_controller = APIRouterPro(order_num=2, tags=['验证码模块']) @captcha_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py index f3a041e..9e48252 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/common_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/common_controller.py @@ -1,16 +1,17 @@ from typing import Annotated -from fastapi import APIRouter, BackgroundTasks, File, Query, Request, Response, UploadFile +from fastapi import BackgroundTasks, File, Query, Request, Response, UploadFile from fastapi.responses import StreamingResponse from common.aspect.pre_auth import PreAuthDependency +from common.router import APIRouterPro from common.vo import DynamicResponseModel from module_admin.entity.vo.common_vo import UploadResponseModel from module_admin.service.common_service import CommonService from utils.log_util import logger from utils.response_util import ResponseUtil -common_controller = APIRouter(prefix='/common', dependencies=[PreAuthDependency()]) +common_controller = APIRouterPro(prefix='/common', order_num=16, tags=['通用模块'], dependencies=[PreAuthDependency()]) @common_controller.post( diff --git a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py index 4de4e58..dddd29b 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/config_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/config_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.config_vo import ConfigModel, ConfigPageQueryModel, DeleteConfigModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -19,7 +20,9 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -config_controller = APIRouter(prefix='/system/config', dependencies=[PreAuthDependency()]) +config_controller = APIRouterPro( + prefix='/system/config', order_num=9, tags=['系统管理-参数管理'], dependencies=[PreAuthDependency()] +) @config_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py index ba08921..6aec56d 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dept_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Path, Query, Request, Response +from fastapi import Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -18,7 +19,9 @@ from module_admin.service.dept_service import DeptService from utils.log_util import logger from utils.response_util import ResponseUtil -dept_controller = APIRouter(prefix='/system/dept', dependencies=[PreAuthDependency()]) +dept_controller = APIRouterPro( + prefix='/system/dept', order_num=6, tags=['系统管理-部门管理'], dependencies=[PreAuthDependency()] +) @dept_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py index 793971a..f5b0297 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/dict_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.dict_vo import ( DeleteDictDataModel, @@ -26,7 +27,9 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -dict_controller = APIRouter(prefix='/system/dict', dependencies=[PreAuthDependency()]) +dict_controller = APIRouterPro( + prefix='/system/dict', order_num=8, tags=['系统管理-字典管理'], dependencies=[PreAuthDependency()] +) @dict_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py index e73afc5..95891e6 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/job_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/job_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.job_vo import ( DeleteJobLogModel, @@ -28,7 +29,9 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -job_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()]) +job_controller = APIRouterPro( + prefix='/monitor', order_num=13, tags=['系统监控-定时任务'], dependencies=[PreAuthDependency()] +) @job_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py index 196abfa..fde3f9d 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/log_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/log_controller.py @@ -1,6 +1,6 @@ from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from sqlalchemy.ext.asyncio import AsyncSession @@ -9,6 +9,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import PageResponseModel, ResponseBaseModel from module_admin.entity.vo.log_vo import ( DeleteLoginLogModel, @@ -24,7 +25,9 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -log_controller = APIRouter(prefix='/monitor', dependencies=[PreAuthDependency()]) +log_controller = APIRouterPro( + prefix='/monitor', order_num=11, tags=['系统管理-日志管理'], dependencies=[PreAuthDependency()] +) @log_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 5c6c2a9..7262d2c 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -3,13 +3,14 @@ from datetime import datetime, timedelta from typing import Annotated, Optional import jwt -from fastapi import APIRouter, Depends, Request, Response +from fastapi import Depends, Request, Response from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log from common.aspect.db_seesion import DBSessionDependency from common.aspect.pre_auth import CurrentUserDependency from common.enums import BusinessType, RedisInitKeyConfig +from common.router import APIRouterPro from common.vo import CrudResponseModel, DataResponseModel, DynamicResponseModel, ResponseBaseModel from config.env import AppConfig, JwtConfig from module_admin.entity.vo.login_vo import RouterModel, Token, UserLogin, UserRegister @@ -19,7 +20,7 @@ from module_admin.service.user_service import UserService from utils.log_util import logger from utils.response_util import ResponseUtil -login_controller = APIRouter() +login_controller = APIRouterPro(order_num=1, tags=['登录模块']) @login_controller.post( diff --git a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py index a9c9b75..d5d8ffc 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/menu_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Path, Query, Request, Response +from fastapi import Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -10,6 +10,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, DynamicResponseModel, ResponseBaseModel from module_admin.entity.vo.menu_vo import DeleteMenuModel, MenuModel, MenuQueryModel, MenuTreeModel from module_admin.entity.vo.role_vo import RoleMenuQueryModel @@ -18,7 +19,9 @@ from module_admin.service.menu_service import MenuService from utils.log_util import logger from utils.response_util import ResponseUtil -menu_controller = APIRouter(prefix='/system/menu', dependencies=[PreAuthDependency()]) +menu_controller = APIRouterPro( + prefix='/system/menu', order_num=5, tags=['系统管理-菜单管理'], dependencies=[PreAuthDependency()] +) @menu_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py index be9cd75..ff904a6 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/notice_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Path, Query, Request, Response +from fastapi import Path, Query, Request, Response from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -10,6 +10,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.notice_vo import DeleteNoticeModel, NoticeModel, NoticePageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -17,7 +18,9 @@ from module_admin.service.notice_service import NoticeService from utils.log_util import logger from utils.response_util import ResponseUtil -notice_controller = APIRouter(prefix='/system/notice', dependencies=[PreAuthDependency()]) +notice_controller = APIRouterPro( + prefix='/system/notice', order_num=10, tags=['系统管理-通知公告管理'], dependencies=[PreAuthDependency()] +) @notice_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py index 7a2299f..ac51647 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/online_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/online_controller.py @@ -1,6 +1,6 @@ from typing import Annotated -from fastapi import APIRouter, Path, Query, Request, Response +from fastapi import Path, Query, Request, Response from sqlalchemy.ext.asyncio import AsyncSession from common.annotation.log_annotation import Log @@ -8,13 +8,16 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import ResponseBaseModel from module_admin.entity.vo.online_vo import DeleteOnlineModel, OnlinePageResponseModel, OnlineQueryModel from module_admin.service.online_service import OnlineService from utils.log_util import logger from utils.response_util import ResponseUtil -online_controller = APIRouter(prefix='/monitor/online', dependencies=[PreAuthDependency()]) +online_controller = APIRouterPro( + prefix='/monitor/online', order_num=12, tags=['系统监控-在线用户'], dependencies=[PreAuthDependency()] +) @online_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py index 66b3357..6a63121 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/post_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/post_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.post_vo import DeletePostModel, PostModel, PostPageQueryModel from module_admin.entity.vo.user_vo import CurrentUserModel @@ -19,7 +20,9 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -post_controller = APIRouter(prefix='/system/post', dependencies=[PreAuthDependency()]) +post_controller = APIRouterPro( + prefix='/system/post', order_num=7, tags=['系统管理-岗位管理'], dependencies=[PreAuthDependency()] +) @post_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py index 907842a..70dcf60 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/role_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/role_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -12,6 +12,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.dept_vo import DeptModel from module_admin.entity.vo.role_vo import ( @@ -29,7 +30,9 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -role_controller = APIRouter(prefix='/system/role', dependencies=[PreAuthDependency()]) +role_controller = APIRouterPro( + prefix='/system/role', order_num=4, tags=['系统管理-角色管理'], dependencies=[PreAuthDependency()] +) @role_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py index 5c0e705..c754689 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/server_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/server_controller.py @@ -1,14 +1,17 @@ -from fastapi import APIRouter, Request, Response +from fastapi import Request, Response from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import PreAuthDependency +from common.router import APIRouterPro from common.vo import DataResponseModel from module_admin.entity.vo.server_vo import ServerMonitorModel from module_admin.service.server_service import ServerService from utils.log_util import logger from utils.response_util import ResponseUtil -server_controller = APIRouter(prefix='/monitor/server', dependencies=[PreAuthDependency()]) +server_controller = APIRouterPro( + prefix='/monitor/server', order_num=14, tags=['系统监控-服务监控'], dependencies=[PreAuthDependency()] +) @server_controller.get( diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py index 50f2235..e14c442 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py @@ -3,7 +3,7 @@ from datetime import datetime from typing import Annotated, Literal, Optional, Union import aiofiles -from fastapi import APIRouter, File, Form, Path, Query, Request, Response, UploadFile +from fastapi import File, Form, Path, Query, Request, Response, UploadFile from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -14,6 +14,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel from config.env import UploadConfig from module_admin.entity.vo.dept_vo import DeptModel, DeptTreeModel @@ -44,7 +45,9 @@ from utils.pwd_util import PwdUtil from utils.response_util import ResponseUtil from utils.upload_util import UploadUtil -user_controller = APIRouter(prefix='/system/user', dependencies=[PreAuthDependency()]) +user_controller = APIRouterPro( + prefix='/system/user', order_num=3, tags=['系统管理-用户管理'], dependencies=[PreAuthDependency()] +) @user_controller.get( diff --git a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py index da2a753..997428a 100644 --- a/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py +++ b/ruoyi-fastapi-backend/module_generator/controller/gen_controller.py @@ -1,7 +1,7 @@ from datetime import datetime from typing import Annotated -from fastapi import APIRouter, Path, Query, Request, Response +from fastapi import Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -11,6 +11,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import RoleInterfaceAuthDependency, UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from config.env import GenConfig from module_admin.entity.vo.user_vo import CurrentUserModel @@ -27,7 +28,7 @@ from utils.common_util import bytes2file_response from utils.log_util import logger from utils.response_util import ResponseUtil -gen_controller = APIRouter(prefix='/tool/gen', dependencies=[PreAuthDependency()]) +gen_controller = APIRouterPro(prefix='/tool/gen', order_num=17, tags=['代码生成'], dependencies=[PreAuthDependency()]) @gen_controller.get( diff --git a/ruoyi-fastapi-backend/server.py b/ruoyi-fastapi-backend/server.py index bb2fbe7..724d8b5 100644 --- a/ruoyi-fastapi-backend/server.py +++ b/ruoyi-fastapi-backend/server.py @@ -5,29 +5,13 @@ from fastapi import FastAPI, applications from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html from fastapi.responses import HTMLResponse +from common.router import auto_register_routers from config.env import AppConfig from config.get_db import init_create_table from config.get_redis import RedisUtil from config.get_scheduler import SchedulerUtil from exceptions.handle import handle_exception from middlewares.handle import handle_middleware -from module_admin.controller.cache_controller import cache_controller -from module_admin.controller.captcha_controller import captcha_controller -from module_admin.controller.common_controller import common_controller -from module_admin.controller.config_controller import config_controller -from module_admin.controller.dept_controller import dept_controller -from module_admin.controller.dict_controller import dict_controller -from module_admin.controller.job_controller import job_controller -from module_admin.controller.log_controller import log_controller -from module_admin.controller.login_controller import login_controller -from module_admin.controller.menu_controller import menu_controller -from module_admin.controller.notice_controller import notice_controller -from module_admin.controller.online_controller import online_controller -from module_admin.controller.post_controller import post_controller -from module_admin.controller.role_controller import role_controller -from module_admin.controller.server_controller import server_controller -from module_admin.controller.user_controller import user_controller -from module_generator.controller.gen_controller import gen_controller from sub_applications.handle import handle_sub_applications from utils.common_util import worship from utils.log_util import logger @@ -88,38 +72,6 @@ def setup_docs_static_resources( applications.get_swagger_ui_html = swagger_ui_monkey_patch -def register_routers(app: FastAPI) -> None: - """ - 注册路由 - - :param app: FastAPI对象 - :return: - """ - # 加载路由列表 - controller_list = [ - {'router': login_controller, 'tags': ['登录模块']}, - {'router': captcha_controller, 'tags': ['验证码模块']}, - {'router': user_controller, 'tags': ['系统管理-用户管理']}, - {'router': role_controller, 'tags': ['系统管理-角色管理']}, - {'router': menu_controller, 'tags': ['系统管理-菜单管理']}, - {'router': dept_controller, 'tags': ['系统管理-部门管理']}, - {'router': post_controller, 'tags': ['系统管理-岗位管理']}, - {'router': dict_controller, 'tags': ['系统管理-字典管理']}, - {'router': config_controller, 'tags': ['系统管理-参数管理']}, - {'router': notice_controller, 'tags': ['系统管理-通知公告管理']}, - {'router': log_controller, 'tags': ['系统管理-日志管理']}, - {'router': online_controller, 'tags': ['系统监控-在线用户']}, - {'router': job_controller, 'tags': ['系统监控-定时任务']}, - {'router': server_controller, 'tags': ['系统监控-服务监控']}, - {'router': cache_controller, 'tags': ['系统监控-缓存监控']}, - {'router': common_controller, 'tags': ['通用模块']}, - {'router': gen_controller, 'tags': ['代码生成']}, - ] - - for controller in controller_list: - app.include_router(router=controller.get('router'), tags=controller.get('tags')) - - def create_app() -> FastAPI: """ 创建FastAPI应用 @@ -142,7 +94,7 @@ def create_app() -> FastAPI: handle_middleware(app) # 加载全局异常处理方法 handle_exception(app) - # 注册路由 - register_routers(app) + # 自动注册路由 + auto_register_routers(app) return app From b1563b0d39c56fc650f03b855bd54dfddd0ffa9b Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Wed, 17 Dec 2025 17:02:42 +0800 Subject: [PATCH 28/49] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=94=9F=E6=88=90=E8=A1=A8=E4=B8=9A=E5=8A=A1=E8=A1=A8?= =?UTF-8?q?=E5=A4=96=E9=94=AE=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_generator/entity/do/gen_do.py | 17 ++++++++++++----- ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql | 3 +-- ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql | 3 +-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py b/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py index 6f9e020..90b25e0 100644 --- a/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py +++ b/ruoyi-fastapi-backend/module_generator/entity/do/gen_do.py @@ -1,7 +1,7 @@ from datetime import datetime -from sqlalchemy import CHAR, BigInteger, Column, DateTime, ForeignKey, Integer, String -from sqlalchemy.orm import relationship +from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, String +from sqlalchemy.orm import foreign, relationship from config.database import Base from config.env import DataBaseConfig @@ -57,7 +57,12 @@ class GenTable(Base): comment='备注', ) - columns = relationship('GenTableColumn', order_by='GenTableColumn.sort', back_populates='tables') + columns = relationship( + 'GenTableColumn', + primaryjoin=lambda: GenTable.table_id == foreign(GenTableColumn.table_id), + order_by='GenTableColumn.sort', + back_populates='tables', + ) class GenTableColumn(Base): @@ -69,7 +74,7 @@ class GenTableColumn(Base): __table_args__ = {'comment': '代码生成业务表字段'} column_id = Column(BigInteger, primary_key=True, autoincrement=True, nullable=False, comment='编号') - table_id = Column(BigInteger, ForeignKey('gen_table.table_id'), nullable=True, comment='归属表编号') + table_id = Column(BigInteger, nullable=True, comment='归属表编号') column_name = Column(String(200), nullable=True, comment='列名称') column_comment = Column(String(500), nullable=True, comment='列描述') column_type = Column(String(100), nullable=True, comment='列类型') @@ -96,4 +101,6 @@ class GenTableColumn(Base): update_by = Column(String(64), server_default="''", comment='更新者') update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') - tables = relationship('GenTable', back_populates='columns') + tables = relationship( + 'GenTable', primaryjoin=lambda: foreign(GenTableColumn.table_id) == GenTable.table_id, back_populates='columns' + ) diff --git a/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql b/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql index 18446b0..4b117aa 100644 --- a/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql +++ b/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql @@ -936,8 +936,7 @@ create table gen_table_column ( create_time timestamp(0), update_by varchar(64) default '', update_time timestamp(0), - primary key (column_id), - constraint fk_gen_table_column_table_id foreign key (table_id) references gen_table(table_id) + primary key (column_id) ); comment on column gen_table_column.column_id is '编号'; comment on column gen_table_column.table_id is '归属表编号'; diff --git a/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql b/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql index e489007..7bc6f3c 100644 --- a/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql +++ b/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql @@ -712,6 +712,5 @@ create table gen_table_column ( create_time datetime comment '创建时间', update_by varchar(64) default '' comment '更新者', update_time datetime comment '更新时间', - primary key (column_id), - foreign key (table_id) references gen_table(table_id) + primary key (column_id) ) engine=innodb auto_increment=1 comment = '代码生成业务表字段'; \ No newline at end of file From b9b2f713b9a2769772e980bbab8f4986d4b714e2 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Thu, 18 Dec 2025 16:03:44 +0800 Subject: [PATCH 29/49] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Edocker=20compos?= =?UTF-8?q?e=E9=83=A8=E7=BD=B2=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.my.yml | 73 +++++++++++++++++++ docker-compose.pg.yml | 66 +++++++++++++++++ ruoyi-fastapi-backend/.env.dockermy | 66 +++++++++++++++++ ruoyi-fastapi-backend/.env.dockerpg | 66 +++++++++++++++++ ruoyi-fastapi-backend/Dockerfile.my | 14 ++++ ruoyi-fastapi-backend/Dockerfile.pg | 14 ++++ ruoyi-fastapi-frontend/.env.docker | 11 +++ ruoyi-fastapi-frontend/Dockerfile | 28 +++++++ .../bin/nginx.dockermy.conf | 24 ++++++ .../bin/nginx.dockerpg.conf | 24 ++++++ ruoyi-fastapi-frontend/package.json | 1 + 11 files changed, 387 insertions(+) create mode 100644 docker-compose.my.yml create mode 100644 docker-compose.pg.yml create mode 100644 ruoyi-fastapi-backend/.env.dockermy create mode 100644 ruoyi-fastapi-backend/.env.dockerpg create mode 100644 ruoyi-fastapi-backend/Dockerfile.my create mode 100644 ruoyi-fastapi-backend/Dockerfile.pg create mode 100644 ruoyi-fastapi-frontend/.env.docker create mode 100644 ruoyi-fastapi-frontend/Dockerfile create mode 100644 ruoyi-fastapi-frontend/bin/nginx.dockermy.conf create mode 100644 ruoyi-fastapi-frontend/bin/nginx.dockerpg.conf diff --git a/docker-compose.my.yml b/docker-compose.my.yml new file mode 100644 index 0000000..d54b0f2 --- /dev/null +++ b/docker-compose.my.yml @@ -0,0 +1,73 @@ +services: + # 前端服务 + ruoyi-frontend: + build: + context: ./ruoyi-fastapi-frontend + dockerfile: Dockerfile + image: ruoyi-frontend:latest + container_name: ruoyi-frontend + ports: + - "12580:80" + volumes: + - ./ruoyi-fastapi-frontend/bin/nginx.dockermy.conf:/etc/nginx/conf.d/default.conf + depends_on: + - ruoyi-backend-my + networks: + - ruoyi-network + + # 后端服务(MySQL版本) + ruoyi-backend-my: + build: + context: ./ruoyi-fastapi-backend + dockerfile: Dockerfile.my + image: ruoyi-backend-my:latest + container_name: ruoyi-backend-my + ports: + - "19099:9099" + depends_on: + ruoyi-mysql: + condition: service_healthy + ruoyi-redis: + condition: service_healthy + networks: + - ruoyi-network + + # MySQL服务 + ruoyi-mysql: + image: mysql:8.0 + container_name: ruoyi-mysql + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: ruoyi-fastapi + ports: + - "13306:3306" + volumes: + - ./ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql:/docker-entrypoint-initdb.d/ruoyi-fastapi.sql + command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --skip-character-set-client-handshake=1 + networks: + - ruoyi-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"] + interval: 5s + timeout: 10s + retries: 30 + + # Redis服务 + ruoyi-redis: + image: redis:latest + container_name: ruoyi-redis + ports: + - "16379:6379" + networks: + - ruoyi-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 10s + retries: 30 + +# 网络配置 +networks: + ruoyi-network: + name: ruoyi-network + driver: bridge \ No newline at end of file diff --git a/docker-compose.pg.yml b/docker-compose.pg.yml new file mode 100644 index 0000000..a8247da --- /dev/null +++ b/docker-compose.pg.yml @@ -0,0 +1,66 @@ +services: + # 前端服务 + ruoyi-frontend: + build: + context: ./ruoyi-fastapi-frontend + dockerfile: Dockerfile + image: ruoyi-frontend:latest + container_name: ruoyi-frontend + ports: + - "12580:80" + volumes: + - ./ruoyi-fastapi-frontend/bin/nginx.dockerpg.conf:/etc/nginx/conf.d/default.conf + depends_on: + - ruoyi-backend-pg + networks: + - ruoyi-network + + # 后端服务(PostgreSQL版本) + ruoyi-backend-pg: + build: + context: ./ruoyi-fastapi-backend + dockerfile: Dockerfile.pg + image: ruoyi-backend-pg:latest + container_name: ruoyi-backend-pg + ports: + - "19099:9099" + depends_on: + - ruoyi-pg + - ruoyi-redis + networks: + - ruoyi-network + + # PostgreSQL服务 + ruoyi-pg: + image: postgres:14 + container_name: ruoyi-pg + environment: + POSTGRES_PASSWORD: root + POSTGRES_DB: ruoyi-fastapi + POSTGRES_INITDB_ARGS: --encoding=UTF8 --lc-collate=C --lc-ctype=C + ports: + - "15432:5432" + volumes: + - ./ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql:/docker-entrypoint-initdb.d/ruoyi-fastapi-pg.sql + networks: + - ruoyi-network + healthcheck: + test: ["CMD", "pg_isready", "-U", "postgres"] + interval: 5s + timeout: 10s + retries: 30 + + # Redis服务 + ruoyi-redis: + image: redis:latest + container_name: ruoyi-redis + ports: + - "16379:6379" + networks: + - ruoyi-network + +# 网络配置 +networks: + ruoyi-network: + name: ruoyi-network + driver: bridge \ No newline at end of file diff --git a/ruoyi-fastapi-backend/.env.dockermy b/ruoyi-fastapi-backend/.env.dockermy new file mode 100644 index 0000000..e7b10d5 --- /dev/null +++ b/ruoyi-fastapi-backend/.env.dockermy @@ -0,0 +1,66 @@ +# -------- 应用配置 -------- +# 应用运行环境 +APP_ENV = 'prod' +# 应用名称 +APP_NAME = 'RuoYi-FastAPI' +# 应用代理路径 +APP_ROOT_PATH = '/docker-api' +# 应用主机 +APP_HOST = '0.0.0.0' +# 应用端口 +APP_PORT = 9099 +# 应用版本 +APP_VERSION= '1.7.1' +# 应用是否开启热重载 +APP_RELOAD = false +# 应用是否开启IP归属区域查询 +APP_IP_LOCATION_QUERY = true +# 应用是否允许账号同时登录 +APP_SAME_TIME_LOGIN = true + +# -------- Jwt配置 -------- +# Jwt秘钥 +JWT_SECRET_KEY = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55' +# Jwt算法 +JWT_ALGORITHM = 'HS256' +# 令牌过期时间 +JWT_EXPIRE_MINUTES = 1440 +# redis中令牌过期时间 +JWT_REDIS_EXPIRE_MINUTES = 30 + + +# -------- 数据库配置 -------- +# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql' +DB_TYPE = 'mysql' +# 数据库主机 +DB_HOST = 'ruoyi-mysql' +# 数据库端口 +DB_PORT = 3306 +# 数据库用户名 +DB_USERNAME = 'root' +# 数据库密码 +DB_PASSWORD = 'root' +# 数据库名称 +DB_DATABASE = 'ruoyi-fastapi' +# 是否开启sqlalchemy日志 +DB_ECHO = true +# 允许溢出连接池大小的最大连接数 +DB_MAX_OVERFLOW = 10 +# 连接池大小,0表示连接数无限制 +DB_POOL_SIZE = 50 +# 连接回收时间(单位:秒) +DB_POOL_RECYCLE = 3600 +# 连接池中没有线程可用时,最多等待的时间(单位:秒) +DB_POOL_TIMEOUT = 30 + +# -------- Redis配置 -------- +# Redis主机 +REDIS_HOST = 'ruoyi-redis' +# Redis端口 +REDIS_PORT = 6379 +# Redis用户名 +REDIS_USERNAME = '' +# Redis密码 +REDIS_PASSWORD = '' +# Redis数据库 +REDIS_DATABASE = 2 \ No newline at end of file diff --git a/ruoyi-fastapi-backend/.env.dockerpg b/ruoyi-fastapi-backend/.env.dockerpg new file mode 100644 index 0000000..e9180a0 --- /dev/null +++ b/ruoyi-fastapi-backend/.env.dockerpg @@ -0,0 +1,66 @@ +# -------- 应用配置 -------- +# 应用运行环境 +APP_ENV = 'prod' +# 应用名称 +APP_NAME = 'RuoYi-FastAPI' +# 应用代理路径 +APP_ROOT_PATH = '/docker-api' +# 应用主机 +APP_HOST = '0.0.0.0' +# 应用端口 +APP_PORT = 9099 +# 应用版本 +APP_VERSION= '1.7.1' +# 应用是否开启热重载 +APP_RELOAD = false +# 应用是否开启IP归属区域查询 +APP_IP_LOCATION_QUERY = true +# 应用是否允许账号同时登录 +APP_SAME_TIME_LOGIN = true + +# -------- Jwt配置 -------- +# Jwt秘钥 +JWT_SECRET_KEY = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55' +# Jwt算法 +JWT_ALGORITHM = 'HS256' +# 令牌过期时间 +JWT_EXPIRE_MINUTES = 1440 +# redis中令牌过期时间 +JWT_REDIS_EXPIRE_MINUTES = 30 + + +# -------- 数据库配置 -------- +# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql' +DB_TYPE = 'postgresql' +# 数据库主机 +DB_HOST = 'ruoyi-pg' +# 数据库端口 +DB_PORT = 5432 +# 数据库用户名 +DB_USERNAME = 'postgres' +# 数据库密码 +DB_PASSWORD = 'root' +# 数据库名称 +DB_DATABASE = 'ruoyi-fastapi' +# 是否开启sqlalchemy日志 +DB_ECHO = true +# 允许溢出连接池大小的最大连接数 +DB_MAX_OVERFLOW = 10 +# 连接池大小,0表示连接数无限制 +DB_POOL_SIZE = 50 +# 连接回收时间(单位:秒) +DB_POOL_RECYCLE = 3600 +# 连接池中没有线程可用时,最多等待的时间(单位:秒) +DB_POOL_TIMEOUT = 30 + +# -------- Redis配置 -------- +# Redis主机 +REDIS_HOST = 'ruoyi-redis' +# Redis端口 +REDIS_PORT = 6379 +# Redis用户名 +REDIS_USERNAME = '' +# Redis密码 +REDIS_PASSWORD = '' +# Redis数据库 +REDIS_DATABASE = 2 \ No newline at end of file diff --git a/ruoyi-fastapi-backend/Dockerfile.my b/ruoyi-fastapi-backend/Dockerfile.my new file mode 100644 index 0000000..0b30847 --- /dev/null +++ b/ruoyi-fastapi-backend/Dockerfile.my @@ -0,0 +1,14 @@ +FROM python:3.10 +WORKDIR /app + +# 复制源代码 +COPY . . + +# 安装依赖 +RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple + +# 暴露端口 +EXPOSE 9099 + +# 启动命令 +CMD ["python", "app.py", "--env=dockermy"] \ No newline at end of file diff --git a/ruoyi-fastapi-backend/Dockerfile.pg b/ruoyi-fastapi-backend/Dockerfile.pg new file mode 100644 index 0000000..b01b03e --- /dev/null +++ b/ruoyi-fastapi-backend/Dockerfile.pg @@ -0,0 +1,14 @@ +FROM python:3.10 +WORKDIR /app + +# 复制源代码 +COPY . . + +# 安装依赖 +RUN pip install --no-cache-dir -r requirements-pg.txt -i https://pypi.tuna.tsinghua.edu.cn/simple + +# 暴露端口 +EXPOSE 9099 + +# 启动命令 +CMD ["python", "app.py", "--env=dockerpg"] \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/.env.docker b/ruoyi-fastapi-frontend/.env.docker new file mode 100644 index 0000000..8487fb4 --- /dev/null +++ b/ruoyi-fastapi-frontend/.env.docker @@ -0,0 +1,11 @@ +# 页面标题 +VITE_APP_TITLE = vfadmin管理系统 + +# 生产环境配置 +VITE_APP_ENV = 'docker' + +# vfadmin管理系统/生产环境 +VITE_APP_BASE_API = '/docker-api' + +# 是否在打包时开启压缩,支持 gzip 和 brotli +VITE_BUILD_COMPRESS = gzip \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/Dockerfile b/ruoyi-fastapi-frontend/Dockerfile new file mode 100644 index 0000000..4235ee5 --- /dev/null +++ b/ruoyi-fastapi-frontend/Dockerfile @@ -0,0 +1,28 @@ +# 构建阶段 +FROM node:18-slim AS builder +WORKDIR /app + +# 复制源代码 +COPY . . + +# 设置npm镜像源 +RUN npm config set registry https://registry.npmmirror.com + +# 安装依赖 +RUN npm install + +# 执行docker构建命令 +RUN npm run build:docker + +# 运行阶段 +FROM nginx:latest +WORKDIR /usr/share/nginx/html + +# 复制构建产物 +COPY --from=builder /app/dist . + +# 暴露端口 +EXPOSE 80 + +# 启动nginx +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/bin/nginx.dockermy.conf b/ruoyi-fastapi-frontend/bin/nginx.dockermy.conf new file mode 100644 index 0000000..c7855c9 --- /dev/null +++ b/ruoyi-fastapi-frontend/bin/nginx.dockermy.conf @@ -0,0 +1,24 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + # API代理配置(MySQL版本) + location /docker-api/ { + proxy_pass http://ruoyi-backend-my:9099/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/bin/nginx.dockerpg.conf b/ruoyi-fastapi-frontend/bin/nginx.dockerpg.conf new file mode 100644 index 0000000..35564d7 --- /dev/null +++ b/ruoyi-fastapi-frontend/bin/nginx.dockerpg.conf @@ -0,0 +1,24 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + # API代理配置(PostgreSQL版本) + location /docker-api/ { + proxy_pass http://ruoyi-backend-pg:9099/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/package.json b/ruoyi-fastapi-frontend/package.json index aaec05c..38339de 100644 --- a/ruoyi-fastapi-frontend/package.json +++ b/ruoyi-fastapi-frontend/package.json @@ -8,6 +8,7 @@ "scripts": { "dev": "vite", "build:prod": "vite build", + "build:docker": "vite build --mode docker", "build:stage": "vite build --mode staging", "preview": "vite preview" }, From ed88512bf8e41e1b3223794e0962d3587f6c2bb9 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 19 Dec 2025 08:23:00 +0800 Subject: [PATCH 30/49] =?UTF-8?q?feat:=20=E4=BB=A3=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E6=88=90controller=E6=A8=A1=E7=89=88=E4=BD=BF=E7=94=A8APIRoute?= =?UTF-8?q?rPro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module_generator/templates/python/controller.py.jinja2 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 index e47e5cc..1c78e62 100644 --- a/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 +++ b/ruoyi-fastapi-backend/module_generator/templates/python/controller.py.jinja2 @@ -13,7 +13,7 @@ from datetime import datetime {% endif %} from typing import Annotated -from fastapi import APIRouter, Form, Path, Query, Request, Response +from fastapi import Form, Path, Query, Request, Response from fastapi.responses import StreamingResponse from pydantic_validation_decorator import ValidateFields from sqlalchemy.ext.asyncio import AsyncSession @@ -23,6 +23,7 @@ from common.aspect.db_seesion import DBSessionDependency from common.aspect.interface_auth import UserInterfaceAuthDependency from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency from common.enums import BusinessType +from common.router import APIRouterPro from common.vo import DataResponseModel, PageResponseModel, ResponseBaseModel from module_admin.entity.vo.user_vo import CurrentUserModel from {{ packageName }}.service.{{ businessName }}_service import {{ BusinessName }}Service @@ -32,7 +33,9 @@ from utils.log_util import logger from utils.response_util import ResponseUtil -{{ businessName }}_controller = APIRouter(prefix='/{{ moduleName }}/{{ businessName }}', dependencies=[PreAuthDependency()]) +{{ businessName }}_controller = APIRouterPro( + prefix='/{{ moduleName }}/{{ businessName }}', order_num=50, tags=['{{ functionName }}'], dependencies=[PreAuthDependency()] +) @{{ businessName }}_controller.get( From d4b85f38d858bd3a6aa1a4af8f50a84673f8fb7d Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 19 Dec 2025 08:38:41 +0800 Subject: [PATCH 31/49] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=9B=BA?= =?UTF-8?q?=E5=AE=9A=E5=A4=B4=E9=83=A8=E6=97=B6=E5=87=BA=E7=8E=B0=E7=9A=84?= =?UTF-8?q?=E5=AF=BC=E8=88=AA=E6=A0=8F=E5=81=8F=E7=A7=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/layout/components/AppMain.vue | 20 ++++++++++--------- ruoyi-fastapi-frontend/src/layout/index.vue | 5 +++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ruoyi-fastapi-frontend/src/layout/components/AppMain.vue b/ruoyi-fastapi-frontend/src/layout/components/AppMain.vue index 0bb8b7e..b47f628 100644 --- a/ruoyi-fastapi-frontend/src/layout/components/AppMain.vue +++ b/ruoyi-fastapi-frontend/src/layout/components/AppMain.vue @@ -44,12 +44,19 @@ function addIframe() { overflow: hidden; } +.fixed-header + .app-main { + overflow-y: auto; + scrollbar-gutter: auto; + height: calc(100vh - 50px); + min-height: 0px; +} + .app-main:has(.copyright) { padding-bottom: 36px; } .fixed-header + .app-main { - padding-top: 50px; + margin-top: 50px; } .hasTagsView { @@ -59,19 +66,14 @@ function addIframe() { } .fixed-header + .app-main { - padding-top: 84px; + margin-top: 84px; + height: calc(100vh - 84px); + min-height: 0px; } } \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/src/layout/components/Sidebar/Logo.vue b/ruoyi-fastapi-frontend/src/layout/components/Sidebar/Logo.vue index 358f2d2..e69b75a 100644 --- a/ruoyi-fastapi-frontend/src/layout/components/Sidebar/Logo.vue +++ b/ruoyi-fastapi-frontend/src/layout/components/Sidebar/Logo.vue @@ -34,6 +34,9 @@ const getLogoBackground = computed(() => { if (settingsStore.isDark) { return 'var(--sidebar-bg)'; } + if (settingsStore.navType == 3) { + return variables.menuLightBg + } return sideTheme.value === 'theme-dark' ? variables.menuBg : variables.menuLightBg; }); @@ -42,6 +45,9 @@ const getLogoTextColor = computed(() => { if (settingsStore.isDark) { return 'var(--sidebar-text)'; } + if (settingsStore.navType == 3) { + return variables.menuLightText + } return sideTheme.value === 'theme-dark' ? '#fff' : variables.menuLightText; }); @@ -58,7 +64,6 @@ const getLogoTextColor = computed(() => { .sidebar-logo-container { position: relative; - width: 100%; height: 50px; line-height: 50px; background: v-bind(getLogoBackground); diff --git a/ruoyi-fastapi-frontend/src/layout/components/TopBar/index.vue b/ruoyi-fastapi-frontend/src/layout/components/TopBar/index.vue new file mode 100644 index 0000000..d5a9733 --- /dev/null +++ b/ruoyi-fastapi-frontend/src/layout/components/TopBar/index.vue @@ -0,0 +1,106 @@ + + + + + \ No newline at end of file diff --git a/ruoyi-fastapi-frontend/src/settings.js b/ruoyi-fastapi-frontend/src/settings.js index d63af71..6ca2a78 100644 --- a/ruoyi-fastapi-frontend/src/settings.js +++ b/ruoyi-fastapi-frontend/src/settings.js @@ -15,9 +15,9 @@ export default { showSettings: true, /** - * 是否显示顶部导航 + * 菜单导航模式 1、纯左侧 2、混合(左侧+顶部) 3、纯顶部 */ - topNav: false, + navType: 1, /** * 是否显示 tagsView diff --git a/ruoyi-fastapi-frontend/src/store/modules/settings.js b/ruoyi-fastapi-frontend/src/store/modules/settings.js index 2913564..eba4df7 100644 --- a/ruoyi-fastapi-frontend/src/store/modules/settings.js +++ b/ruoyi-fastapi-frontend/src/store/modules/settings.js @@ -5,7 +5,7 @@ import { useDynamicTitle } from '@/utils/dynamicTitle' const isDark = useDark() const toggleDark = useToggle(isDark) -const { sideTheme, showSettings, topNav, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings +const { sideTheme, showSettings, navType, tagsView, tagsIcon, fixedHeader, sidebarLogo, dynamicTitle, footerVisible, footerContent } = defaultSettings const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' @@ -17,7 +17,7 @@ const useSettingsStore = defineStore( theme: storageSetting.theme || '#409EFF', sideTheme: storageSetting.sideTheme || sideTheme, showSettings: showSettings, - topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, + navType: storageSetting.navType === undefined ? navType : storageSetting.navType, tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, tagsIcon: storageSetting.tagsIcon === undefined ? tagsIcon : storageSetting.tagsIcon, fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, From c8da8d54069034ffcfd00528b394eca2db0685be Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 19 Dec 2025 09:24:40 +0800 Subject: [PATCH 38/49] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E5=BF=97=E8=AF=A6=E7=BB=86=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-frontend/src/views/monitor/operlog/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-fastapi-frontend/src/views/monitor/operlog/index.vue b/ruoyi-fastapi-frontend/src/views/monitor/operlog/index.vue index 779ee92..0d55881 100644 --- a/ruoyi-fastapi-frontend/src/views/monitor/operlog/index.vue +++ b/ruoyi-fastapi-frontend/src/views/monitor/operlog/index.vue @@ -166,7 +166,7 @@ {{ form.method }} - {{ form.operParam }} + {{ form.operParam }} {{ form.jsonResult }} From 67c09f3113a6208e79ef758c7aa2a653f365421f Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 19 Dec 2025 09:25:32 +0800 Subject: [PATCH 39/49] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96index=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=A0=87=E9=A2=98=E8=AF=BB=E5=8F=96=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-frontend/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruoyi-fastapi-frontend/index.html b/ruoyi-fastapi-frontend/index.html index ab221b8..17457d3 100644 --- a/ruoyi-fastapi-frontend/index.html +++ b/ruoyi-fastapi-frontend/index.html @@ -7,7 +7,7 @@ - vfadmin管理系统 + %VITE_APP_TITLE%