diff --git a/kinit-admin/src/views/vadmin/auth/user/components/user.data.ts b/kinit-admin/src/views/vadmin/auth/user/components/user.data.ts index 81241a7..7d29caf 100644 --- a/kinit-admin/src/views/vadmin/auth/user/components/user.data.ts +++ b/kinit-admin/src/views/vadmin/auth/user/components/user.data.ts @@ -45,11 +45,13 @@ export const columns = reactive([ { field: 'last_login', label: '最近登录时间', - show: true + show: true, + width: '190px' }, { field: 'create_datetime', label: '创建时间', + width: '190px', show: true }, { diff --git a/kinit-admin/src/views/vadmin/help/issue/components/issue.data.ts b/kinit-admin/src/views/vadmin/help/issue/components/issue.data.ts index 15a76e2..0bea240 100644 --- a/kinit-admin/src/views/vadmin/help/issue/components/issue.data.ts +++ b/kinit-admin/src/views/vadmin/help/issue/components/issue.data.ts @@ -14,6 +14,7 @@ export const columns = reactive([ { field: 'category.name', label: '类别名称', + width: '200px', show: true, disabled: true, span: 24 @@ -28,18 +29,21 @@ export const columns = reactive([ field: 'view_number', label: '查看次数', show: true, + width: '100px', span: 24 }, { field: 'is_active', label: '是否可见', show: true, + width: '100px', span: 24 }, { field: 'create_datetime', label: '创建时间', show: true, + width: '200px', span: 24, sortable: true }, @@ -47,6 +51,7 @@ export const columns = reactive([ field: 'user.name', label: '创建人', show: true, + width: '100px', span: 24 }, { diff --git a/kinit-admin/src/views/vadmin/system/record/operation/components/operation.data.ts b/kinit-admin/src/views/vadmin/system/record/operation/components/operation.data.ts index 7836638..72b73a4 100644 --- a/kinit-admin/src/views/vadmin/system/record/operation/components/operation.data.ts +++ b/kinit-admin/src/views/vadmin/system/record/operation/components/operation.data.ts @@ -3,6 +3,22 @@ import { TableColumn } from '@/types/table' import { reactive } from 'vue' export const columns = reactive([ + { + field: 'user_id', + label: '操作人编号', + show: true, + disabled: true, + width: '100px', + span: 24 + }, + { + field: 'user_name', + label: '操作人', + show: true, + disabled: true, + width: '100px', + span: 24 + }, { field: 'telephone', label: '手机号', @@ -82,7 +98,7 @@ export const columns = reactive([ { field: 'system', label: '系统', - show: true, + show: false, width: '150px', span: 24 }, diff --git a/kinit-api/README.md b/kinit-api/README.md index 05e1def..5275d3c 100644 --- a/kinit-api/README.md +++ b/kinit-api/README.md @@ -43,7 +43,7 @@ Typer 官方文档:https://typer.tiangolo.com/ 开发语言:Python 3.10 -开发框架:Fastapi 0.87.0 +开发框架:Fastapi 0.94.1 ## 使用 diff --git a/kinit-api/application/settings.py b/kinit-api/application/settings.py index c5d2935..afe6e6e 100644 --- a/kinit-api/application/settings.py +++ b/kinit-api/application/settings.py @@ -11,7 +11,7 @@ from fastapi.security import OAuth2PasswordBearer """ 系统版本 """ -VERSION = "1.6.2" +VERSION = "1.6.3" """安全警告: 不要在生产中打开调试运行!""" DEBUG = True @@ -101,8 +101,8 @@ ALLOW_HEADERS = ["*"] 全局事件配置 """ EVENTS = [ - "core.event.register_mongo" if MONGO_DB_ENABLE else None, - "core.event.register_redis" if REDIS_DB_ENABLE else None, + "core.event.connect_mongo" if MONGO_DB_ENABLE else None, + "core.event.connect_redis" if REDIS_DB_ENABLE else None, ] """ diff --git a/kinit-api/apps/vadmin/auth/utils/current.py b/kinit-api/apps/vadmin/auth/utils/current.py index 252534b..7a098fc 100644 --- a/kinit-api/apps/vadmin/auth/utils/current.py +++ b/kinit-api/apps/vadmin/auth/utils/current.py @@ -76,6 +76,8 @@ class OpenAuth(AuthValidation): return Auth(db=db) elif not user.is_active: return Auth(db=db) + request.scope["user_id"] = user.id + request.scope["user_name"] = user.name request.scope["telephone"] = user.telephone try: request.scope["body"] = await request.body() diff --git a/kinit-api/apps/vadmin/auth/utils/validation/auth.py b/kinit-api/apps/vadmin/auth/utils/validation/auth.py index b8acde0..36ee088 100644 --- a/kinit-api/apps/vadmin/auth/utils/validation/auth.py +++ b/kinit-api/apps/vadmin/auth/utils/validation/auth.py @@ -70,6 +70,8 @@ class AuthValidation: raise CustomException(msg="未认证,请您重新登陆", code=cls.error_code, status_code=cls.error_code) elif not user.is_active: raise CustomException(msg="用户已被冻结!", code=cls.error_code, status_code=cls.error_code) + request.scope["user_id"] = user.id + request.scope["user_name"] = user.name request.scope["telephone"] = user.telephone try: request.scope["body"] = await request.body() diff --git a/kinit-api/apps/vadmin/record/schemas/operation.py b/kinit-api/apps/vadmin/record/schemas/operation.py index 4ca150e..e536988 100644 --- a/kinit-api/apps/vadmin/record/schemas/operation.py +++ b/kinit-api/apps/vadmin/record/schemas/operation.py @@ -15,6 +15,8 @@ from pydantic import BaseModel class OpertionRecord(BaseModel): telephone: Optional[str] = None + user_id: Optional[str] = None + user_name: Optional[str] = None status_code: Optional[int] = None request_ip: Optional[str] = None request_method: Optional[str] = None diff --git a/kinit-api/core/event.py b/kinit-api/core/event.py index 8fddd26..20a322b 100644 --- a/kinit-api/core/event.py +++ b/kinit-api/core/event.py @@ -8,13 +8,25 @@ from fastapi import FastAPI -from aioredis import from_url -from application.settings import REDIS_DB_URL, MONGO_DB_URL, MONGO_DB_NAME +from application.settings import REDIS_DB_URL, MONGO_DB_URL, MONGO_DB_NAME, EVENTS from core.mongo import db from utils.cache import Cache +import aioredis +from contextlib import asynccontextmanager +from utils.tools import import_modules_async -def register_redis(app: FastAPI) -> None: +@asynccontextmanager +async def lifespan(app: FastAPI): + + await import_modules_async(EVENTS, "全局事件", app=app, status=True) + + yield + + await import_modules_async(EVENTS, "全局事件", app=app, status=False) + + +async def connect_redis(app: FastAPI, status: bool): """ 把 redis 挂载到 app 对象上面 @@ -46,30 +58,20 @@ def register_redis(app: FastAPI) -> None: 该参数的默认值是 0,表示不进行健康检查。如果需要启用健康检查,则可以将该参数设置为一个正整数,表示检查间隔的秒数。 例如,如果需要每隔 5 秒对 Redis 连接进行一次健康检查,则可以将 health_check_interval 设置为 5 :param app: + :param status: :return: """ - - @app.on_event('startup') - async def startup_event(): - """ - 获取链接 - :return: - """ + if status: print("Connecting to Redis") - app.state.redis = from_url(REDIS_DB_URL, decode_responses=True, health_check_interval=1) + assert isinstance(app, FastAPI) + app.state.redis = aioredis.from_url(REDIS_DB_URL, decode_responses=True, health_check_interval=1) await Cache(app.state.redis).cache_tab_names() - - @app.on_event('shutdown') - async def shutdown_event(): - """ - 关闭 - :return: - """ + else: print("Redis connection closed") await app.state.redis.close() -def register_mongo(app: FastAPI) -> None: +async def connect_mongo(app: FastAPI, status: bool): """ 把 mongo 挂载到 app 对象上面 @@ -77,21 +79,16 @@ def register_mongo(app: FastAPI) -> None: mongodb 官网:https://www.mongodb.com/docs/drivers/motor/ motor 文档:https://motor.readthedocs.io/en/stable/ :param app: + :param status: :return: """ - - @app.on_event('startup') - async def startup_event(): - """ - 获取 mongodb 连接 - :return: - """ + if status: + print("Connecting to Mongo") await db.connect_to_database(path=MONGO_DB_URL, db_name=MONGO_DB_NAME) - - @app.on_event('shutdown') - async def shutdown_event(): - """ - 关闭 - :return: - """ + else: + print("Mongo connection closed") await db.close_database_connection() + + + + diff --git a/kinit-api/core/middleware.py b/kinit-api/core/middleware.py index a7fc810..bc5056b 100644 --- a/kinit-api/core/middleware.py +++ b/kinit-api/core/middleware.py @@ -69,6 +69,8 @@ def register_operation_record_middleware(app: FastAPI): if not MONGO_DB_ENABLE: return response telephone = request.scope.get('telephone', None) + user_id = request.scope.get('user_id', None) + user_name = request.scope.get('user_name', None) route = request.scope.get('route') if not telephone: return response @@ -98,6 +100,8 @@ def register_operation_record_middleware(app: FastAPI): document = { "process_time": process_time, "telephone": telephone, + "user_id": user_id, + "user_name": user_name, "request_api": request.url.__str__(), "request_ip": request.client.host, "system": system, diff --git a/kinit-api/core/mongo/mongo_manage.py b/kinit-api/core/mongo/mongo_manage.py index 40f1acf..ee9ca8c 100644 --- a/kinit-api/core/mongo/mongo_manage.py +++ b/kinit-api/core/mongo/mongo_manage.py @@ -21,13 +21,11 @@ class MongoManage(DatabaseManage): db: AsyncIOMotorDatabase = None async def connect_to_database(self, path: str, db_name: str): - print("Connecting to MongoDB") self.client = AsyncIOMotorClient(path, maxPoolSize=10, minPoolSize=10) self.db = self.client[db_name] async def close_database_connection(self): self.client.close() - print("MongoDB connection closed") async def create_data(self, collection: str, data: dict) -> InsertOneResult: return await self.db[collection].insert_one(data) diff --git a/kinit-api/main.py b/kinit-api/main.py index 1ee7778..275bccf 100644 --- a/kinit-api/main.py +++ b/kinit-api/main.py @@ -17,19 +17,19 @@ from starlette.middleware.cors import CORSMiddleware from application import settings from application import urls from starlette.staticfiles import StaticFiles # 依赖安装:pip install aiofiles -import importlib -from core.logger import logger from core.exception import register_exception import typer from scripts.initialize.initialize import InitializeData, Environment import asyncio from scripts.create_app.main import CreateApp +from core.event import lifespan +from utils.tools import import_modules shell_app = typer.Typer() -def init_app(): +def create_app(): """ 启动项目 @@ -40,24 +40,10 @@ def init_app(): app = FastAPI( title="Kinit", description="本项目基于Fastapi与Vue3+Typescript+Vite4+element-plus的基础项目 前端基于vue-element-plus-admin框架开发", - version="1.0.0" + version=settings.VERSION, + lifespan=lifespan ) - - def import_module(modules: list, desc: str): - for module in modules: - if not module: - continue - try: - # 动态导入模块 - module_pag = importlib.import_module(module[0:module.rindex(".")]) - getattr(module_pag, module[module.rindex(".") + 1:])(app) - except ModuleNotFoundError: - logger.error(f"AttributeError:导入{desc}失败,未找到该模块:{module}") - except AttributeError: - logger.error(f"ModuleNotFoundError:导入{desc}失败,未找到该模块下的方法:{module}") - - import_module(settings.MIDDLEWARES, "中间件") - import_module(settings.EVENTS, "全局事件") + import_modules(settings.MIDDLEWARES, "中间件", app=app) # 全局异常捕捉处理 register_exception(app) # 跨域解决 @@ -83,8 +69,11 @@ def init_app(): def run(): """ 启动项目 + + factory: 在使用 uvicorn.run() 启动 ASGI 应用程序时,可以通过设置 factory 参数来指定应用程序工厂。 + 应用程序工厂是一个返回 ASGI 应用程序实例的可调用对象,它可以在启动时动态创建应用程序实例。 """ - uvicorn.run(app='main:init_app', host="0.0.0.0", port=9000) + uvicorn.run(app='main:create_app', host="0.0.0.0", port=9000, lifespan="on", factory=True) @shell_app.command() @@ -111,7 +100,7 @@ def migrate(env: Environment = Environment.pro): @shell_app.command() -def create_app(path: str): +def init_app(path: str): """ 自动创建初始化 APP 结构 diff --git a/kinit-api/requirements.txt b/kinit-api/requirements.txt index 5a3c451..7899e11 100644 Binary files a/kinit-api/requirements.txt and b/kinit-api/requirements.txt differ diff --git a/kinit-api/utils/tools.py b/kinit-api/utils/tools.py index dbf62ae..93e0066 100644 --- a/kinit-api/utils/tools.py +++ b/kinit-api/utils/tools.py @@ -11,6 +11,8 @@ import random import re import string from typing import List, Union +import importlib +from core.logger import logger def test_password(password: str) -> Union[str, bool]: @@ -73,6 +75,34 @@ def generate_string(length: int = 8) -> str: return ''.join(random.sample(string.ascii_letters + string.digits, length)) +def import_modules(modules: list, desc: str, **kwargs): + for module in modules: + if not module: + continue + try: + # 动态导入模块 + module_pag = importlib.import_module(module[0:module.rindex(".")]) + getattr(module_pag, module[module.rindex(".") + 1:])(**kwargs) + except ModuleNotFoundError: + logger.error(f"AttributeError:导入{desc}失败,未找到该模块:{module}") + except AttributeError: + logger.error(f"ModuleNotFoundError:导入{desc}失败,未找到该模块下的方法:{module}") + + +async def import_modules_async(modules: list, desc: str, **kwargs): + for module in modules: + if not module: + continue + try: + # 动态导入模块 + module_pag = importlib.import_module(module[0:module.rindex(".")]) + await getattr(module_pag, module[module.rindex(".") + 1:])(**kwargs) + except ModuleNotFoundError: + logger.error(f"AttributeError:导入{desc}失败,未找到该模块:{module}") + except AttributeError: + logger.error(f"ModuleNotFoundError:导入{desc}失败,未找到该模块下的方法:{module}") + + if __name__ == '__main__': # print(generate_invitation_code()) # print(int(datetime.datetime.now().timestamp()))