From 3de880524cdd49ed75e47a40027e3c85731c5140 Mon Sep 17 00:00:00 2001 From: ktianc Date: Wed, 15 Mar 2023 10:58:36 +0800 Subject: [PATCH] =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8D=87=E7=BA=A7=201.=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=88kinit-api=EF=BC=8Ckinit-admin?= =?UTF-8?q?=EF=BC=89=EF=BC=9A=E6=96=B0=E5=A2=9E=E6=93=8D=E4=BD=9C=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=AD=97=E6=AE=B5=202.=20=E6=9B=B4=E6=96=B0=EF=BC=88k?= =?UTF-8?q?init-api=EF=BC=89=EF=BC=9A=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E5=BA=93=203.=20=E6=9B=B4=E6=96=B0=EF=BC=88k?= =?UTF-8?q?init-api=EF=BC=89=EF=BC=9A=E6=9B=B4=E6=96=B0=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E4=BA=8B=E4=BB=B6=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vadmin/auth/user/components/user.data.ts | 4 +- .../help/issue/components/issue.data.ts | 5 ++ .../operation/components/operation.data.ts | 18 ++++- kinit-api/README.md | 2 +- kinit-api/application/settings.py | 6 +- kinit-api/apps/vadmin/auth/utils/current.py | 2 + .../apps/vadmin/auth/utils/validation/auth.py | 2 + .../apps/vadmin/record/schemas/operation.py | 2 + kinit-api/core/event.py | 63 +++++++++--------- kinit-api/core/middleware.py | 4 ++ kinit-api/core/mongo/mongo_manage.py | 2 - kinit-api/main.py | 33 +++------ kinit-api/requirements.txt | Bin 3246 -> 1539 bytes kinit-api/utils/tools.py | 30 +++++++++ 14 files changed, 110 insertions(+), 63 deletions(-) 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 5a3c45186feb572981f72497fd9b4ae4c86a0d51..7899e11d268c6a4e8423bc5f9c0b524fa47052cf 100644 GIT binary patch literal 1539 zcmZuxO>^2X5WVZaSmQ59IQWobI%S3q?W8>lSr`RdQYAScetq8xnjuYZ+V8h-cO|qv z#OS)N;g7swLR+tT9lEaOC9g;hdN5+_x{5cX7}d1XlElX>>YdmLIoi1|Btn&mT8xM< z;atmERuAQ(UR;aR^+zvddS|tX#T+%tmcRjA_jv{p)k&lxIDNGfth+ka zDT6Za3DC+%hp5DV0YYEgg0J@Fr?~f|;On#TJlzoIp3-azm*T;iBJ{^Xf?8_1YIu_q z|6@N+nf7W)a81&dhO*>H6$b6qp2S5KlaWQ#ld^N{x)ubH50q0P*fn1;5u>MUsD^Ai z>65#;R!k}%^&ZsKCG0C+w@mIyu6VV;OyxoNpkiUHpTO%y`HY$@qn5|6!{9LzX-DhD zl$mV#l1VQo+f$YYyiv~%Ubq7wHII3Qy$M$~C>?+?CHs)WD>yJz1burwf+Qe;W-mg- z9I2;O3;(^h7iC5r&`?dI?P6cW<$N@6o;y!@Cqa`+Vg1bbvYMM=-!}w z!&{~&XMMyD6_bjh7ZG}Rkk7ltt6*m@6=(%ZWP6=da3UUZ1yYQ5nEgy5&2TM_7-5B0 zTfF^oc3ZK(ZUCB@Y_uR2H$}ocM%`ost8Z7#vGle;XIuC{F zI1vJ%XXa6AqsP&nx^9&Z&?ON}=AgyGx+EP9H&3*#NY0b$?F3-JLbSNl3tVx&ar9ZU zP5Sckoyz5EX|iTOV{M+mCau%<+gB=1uD5mXZB*ush^T3hH*M|`_0c6=^#X~1J*^Q- zdA<5Qs}S=E)bzD@+Kra4SkPxmpYI|VjaALG()WVOPoq32TKtN)ylwAP#SeTS$cO)f zzP9c5d0lLtZ&0h2VYxhZC!%xUT%u%5j;Ja519C&qW+>DdtpsfiGNAwrvnc+Oh|y5o z>_-fsAqa$w@?c80cWiJkpce1uKt=BEWjfPTDkefkTvZ z>X`wg`8kI3i`S8G(rPp;p$oDSXBX}ASDx4Nf+gbW4Il_PO*U)rwJN_C5-At?KluX~ C`PB^o literal 3246 zcma);OK;m&5QXo$Kz|AiOR^JZkwumX8o-5Hv|SZ8^{`@#bScS}{Nvl6Zw{|6RX0vR zFlID!&zw2)ApiOMIxSP1Zqr8BLwc`kl1|cv?n(MF{g7<$(kxBoxekx9tf#t11CO<= zi`2;fK72-jP<-x%uu3=bsttaM*1!(|%l#3;Shzvp^BKgwvVU!3*V(BLr@PAeoBRpJRRXALLwdL3mUE*mNG zq`!M%tb-ZqXM}I*(&_|UoYPAduF>l(U~nDzf3KE4Q7QXj^vs)Ty!nQH8R5UGx$C}% zZc}Sm1@HbY{K^}V!ZTS=}cCiY|eZ2ndYva z6MC9F^Q7FwOzox5F}6FdR@^Qa%*EDOo(chsce=;vEMnAYuFD=^j}$vkb1l`cBmPWC zm9j$fm40KYo+CohubjeKt4i3s8}b&ag}_eegaJ;@8C~3Q?1@^oR&~Y-r?)-RPAZXY zs|tYdAb!?u5^>7JPQ{g3ES-~iT0{DCra05sCYi;kN3oTR-J$5i-phPS4d!C879&q@ z#<>vVT&1~~wxLxMs^Oh+=qzt%@|o$v2d(jdDH*w*i;cWI?x;CL;6wx3TJr(nH2MTTo3ZG}a5 znuEIyzGm?y(5W5Rw}Who4;_Rao$jo8ncmMjc_)voGCDdJES+pyp>Tz-W-yk2KF@^aIh-mE z-H>zi_Hd4%(II}{m#>9UDB(;mnGs<{HpY; zShC^DR`5Qx&R0_Sqq3~hrT!i(J?e4213O``8PGZFHPm<`R(x-`uTZn>N!$1qTckhb zvkMfqIPYQpg6Ldw&9+jI?}Pk~D!8MVN%t&!;$9curIUlY7WBj-ymKI_zjE-aie6HoE8cv7 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()))