Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
84a02a42aa | ||
![]() |
c750908c04 | ||
![]() |
af89388294 | ||
![]() |
09380dc94f | ||
![]() |
82c84b2afe | ||
![]() |
f404aba689 | ||
![]() |
9013b1917e | ||
![]() |
c415dfa8e1 | ||
![]() |
5765e967ae | ||
![]() |
1ba4d959ce | ||
![]() |
df8ab6bc55 | ||
![]() |
ca6668331f | ||
![]() |
d49d05b776 | ||
![]() |
d8e3f7dca1 | ||
![]() |
5ee1a64587 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,6 +18,7 @@ lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
vf_admin/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi-Vue3-FastAPI v1.3.1</h1>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi-Vue3-FastAPI v1.3.3</h1>
|
||||
<h4 align="center">基于RuoYi-Vue3+FastAPI前后端分离的快速开发框架</h4>
|
||||
<p align="center">
|
||||
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI/stargazers"><img src="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI/badge/star.svg?theme=dark"></a>
|
||||
<a href="https://github.com/insistence/RuoYi-Vue3-FastAPI"><img src="https://img.shields.io/github/stars/insistence/RuoYi-Vue3-FastAPI?style=social"></a>
|
||||
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI"><img src="https://img.shields.io/badge/RuoYiVue3FastAPI-v1.3.1-brightgreen.svg"></a>
|
||||
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI"><img src="https://img.shields.io/badge/RuoYiVue3FastAPI-v1.3.3-brightgreen.svg"></a>
|
||||
<a href="https://gitee.com/insistence2022/RuoYi-Vue3-FastAPI/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
|
||||
<img src="https://img.shields.io/badge/python-≥3.9-blue">
|
||||
<img src="https://img.shields.io/badge/MySQL-≥5.7-blue">
|
||||
|
@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
|
||||
# 应用端口
|
||||
APP_PORT = 9099
|
||||
# 应用版本
|
||||
APP_VERSION= '1.3.1'
|
||||
APP_VERSION= '1.3.3'
|
||||
# 应用是否开启热重载
|
||||
APP_RELOAD = true
|
||||
# 应用是否开启IP归属区域查询
|
||||
|
@@ -10,7 +10,7 @@ APP_HOST = '0.0.0.0'
|
||||
# 应用端口
|
||||
APP_PORT = 9099
|
||||
# 应用版本
|
||||
APP_VERSION= '1.3.1'
|
||||
APP_VERSION= '1.3.3'
|
||||
# 应用是否开启热重载
|
||||
APP_RELOAD = false
|
||||
# 应用是否开启IP归属区域查询
|
||||
|
@@ -221,39 +221,40 @@ class SchedulerUtil:
|
||||
if event_type == 'JobExecutionEvent' and event.exception:
|
||||
exception_info = str(event.exception)
|
||||
status = '1'
|
||||
job_id = event.job_id
|
||||
query_job = cls.get_scheduler_job(job_id=job_id)
|
||||
if query_job:
|
||||
query_job_info = query_job.__getstate__()
|
||||
# 获取任务名称
|
||||
job_name = query_job_info.get('name')
|
||||
# 获取任务组名
|
||||
job_group = query_job._jobstore_alias
|
||||
# 获取任务执行器
|
||||
job_executor = query_job_info.get('executor')
|
||||
# 获取调用目标字符串
|
||||
invoke_target = query_job_info.get('func')
|
||||
# 获取调用函数位置参数
|
||||
job_args = ','.join(query_job_info.get('args'))
|
||||
# 获取调用函数关键字参数
|
||||
job_kwargs = json.dumps(query_job_info.get('kwargs'))
|
||||
# 获取任务触发器
|
||||
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_log = JobLogModel(
|
||||
jobName=job_name,
|
||||
jobGroup=job_group,
|
||||
jobExecutor=job_executor,
|
||||
invokeTarget=invoke_target,
|
||||
jobArgs=job_args,
|
||||
jobKwargs=job_kwargs,
|
||||
jobTrigger=job_trigger,
|
||||
jobMessage=job_message,
|
||||
status=status,
|
||||
exceptionInfo=exception_info,
|
||||
createTime=datetime.now(),
|
||||
)
|
||||
session = SessionLocal()
|
||||
JobLogService.add_job_log_services(session, job_log)
|
||||
session.close()
|
||||
if hasattr(event, 'job_id'):
|
||||
job_id = event.job_id
|
||||
query_job = cls.get_scheduler_job(job_id=job_id)
|
||||
if query_job:
|
||||
query_job_info = query_job.__getstate__()
|
||||
# 获取任务名称
|
||||
job_name = query_job_info.get('name')
|
||||
# 获取任务组名
|
||||
job_group = query_job._jobstore_alias
|
||||
# 获取任务执行器
|
||||
job_executor = query_job_info.get('executor')
|
||||
# 获取调用目标字符串
|
||||
invoke_target = query_job_info.get('func')
|
||||
# 获取调用函数位置参数
|
||||
job_args = ','.join(query_job_info.get('args'))
|
||||
# 获取调用函数关键字参数
|
||||
job_kwargs = json.dumps(query_job_info.get('kwargs'))
|
||||
# 获取任务触发器
|
||||
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_log = JobLogModel(
|
||||
jobName=job_name,
|
||||
jobGroup=job_group,
|
||||
jobExecutor=job_executor,
|
||||
invokeTarget=invoke_target,
|
||||
jobArgs=job_args,
|
||||
jobKwargs=job_kwargs,
|
||||
jobTrigger=job_trigger,
|
||||
jobMessage=job_message,
|
||||
status=status,
|
||||
exceptionInfo=exception_info,
|
||||
createTime=datetime.now(),
|
||||
)
|
||||
session = SessionLocal()
|
||||
JobLogService.add_job_log_services(session, job_log)
|
||||
session.close()
|
||||
|
@@ -3,6 +3,12 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
|
||||
def add_cors_middleware(app: FastAPI):
|
||||
"""
|
||||
添加跨域中间件
|
||||
|
||||
:param app: FastAPI对象
|
||||
:return:
|
||||
"""
|
||||
# 前端页面url
|
||||
origins = [
|
||||
'http://localhost:80',
|
||||
|
12
ruoyi-fastapi-backend/middlewares/gzip_middleware.py
Normal file
12
ruoyi-fastapi-backend/middlewares/gzip_middleware.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.middleware.gzip import GZipMiddleware
|
||||
|
||||
|
||||
def add_gzip_middleware(app: FastAPI):
|
||||
"""
|
||||
添加gzip压缩中间件
|
||||
|
||||
:param app: FastAPI对象
|
||||
:return:
|
||||
"""
|
||||
app.add_middleware(GZipMiddleware, minimum_size=1000, compresslevel=9)
|
@@ -1,5 +1,6 @@
|
||||
from fastapi import FastAPI
|
||||
from middlewares.cors_middleware import add_cors_middleware
|
||||
from middlewares.gzip_middleware import add_gzip_middleware
|
||||
|
||||
|
||||
def handle_middleware(app: FastAPI):
|
||||
@@ -8,3 +9,5 @@ def handle_middleware(app: FastAPI):
|
||||
"""
|
||||
# 加载跨域中间件
|
||||
add_cors_middleware(app)
|
||||
# 加载gzip压缩中间件
|
||||
add_gzip_middleware(app)
|
||||
|
@@ -16,6 +16,7 @@ from module_admin.service.login_service import LoginService
|
||||
from config.enums import BusinessType
|
||||
from config.env import AppConfig
|
||||
from exceptions.exception import LoginException, ServiceException, ServiceWarning
|
||||
from utils.log_util import logger
|
||||
from utils.response_util import ResponseUtil
|
||||
|
||||
|
||||
@@ -116,13 +117,14 @@ class Log:
|
||||
try:
|
||||
# 调用原始函数
|
||||
result = await func(*args, **kwargs)
|
||||
except LoginException as e:
|
||||
except (LoginException, ServiceWarning) as e:
|
||||
logger.warning(e.message)
|
||||
result = ResponseUtil.failure(data=e.data, msg=e.message)
|
||||
except ServiceException as e:
|
||||
logger.error(e.message)
|
||||
result = ResponseUtil.error(data=e.data, msg=e.message)
|
||||
except ServiceWarning as e:
|
||||
result = ResponseUtil.failure(data=e.data, msg=e.message)
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
result = ResponseUtil.error(msg=str(e))
|
||||
# 获取请求耗时
|
||||
cost_time = float(time.time() - start_time) * 100
|
||||
@@ -295,13 +297,14 @@ def log_decorator(
|
||||
try:
|
||||
# 调用原始函数
|
||||
result = await func(*args, **kwargs)
|
||||
except LoginException as e:
|
||||
except (LoginException, ServiceWarning) as e:
|
||||
logger.warning(e.message)
|
||||
result = ResponseUtil.failure(data=e.data, msg=e.message)
|
||||
except ServiceException as e:
|
||||
logger.error(e.message)
|
||||
result = ResponseUtil.error(data=e.data, msg=e.message)
|
||||
except ServiceWarning as e:
|
||||
result = ResponseUtil.failure(data=e.data, msg=e.message)
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
result = ResponseUtil.error(msg=str(e))
|
||||
# 获取请求耗时
|
||||
cost_time = float(time.time() - start_time) * 100
|
||||
|
@@ -13,10 +13,10 @@ class OnlineModel(BaseModel):
|
||||
model_config = ConfigDict(alias_generator=to_camel)
|
||||
|
||||
token_id: Optional[str] = Field(default=None, description='会话编号')
|
||||
user_name: Optional[str] = Field(default=None, description='部门名称')
|
||||
dept_name: Optional[str] = Field(default=None, description='用户名称')
|
||||
ipaddr: Optional[str] = Field(default=None, description='登录IP地址')
|
||||
login_location: Optional[str] = Field(default=None, description='登录地址')
|
||||
user_name: Optional[str] = Field(default=None, description='登录名称')
|
||||
dept_name: Optional[str] = Field(default=None, description='所属部门')
|
||||
ipaddr: Optional[str] = Field(default=None, description='主机')
|
||||
login_location: Optional[str] = Field(default=None, description='登录地点')
|
||||
browser: Optional[str] = Field(default=None, description='浏览器类型')
|
||||
os: Optional[str] = Field(default=None, description='操作系统')
|
||||
login_time: Optional[datetime] = Field(default=None, description='登录时间')
|
||||
|
@@ -22,7 +22,7 @@ class OnlineService:
|
||||
:param query_object: 查询参数对象
|
||||
:return: 在线用户列表信息
|
||||
"""
|
||||
access_token_keys = await request.app.state.redis.keys(f"{RedisInitKeyConfig.ACCESS_TOKEN.key}*")
|
||||
access_token_keys = await request.app.state.redis.keys(f'{RedisInitKeyConfig.ACCESS_TOKEN.key}*')
|
||||
if not access_token_keys:
|
||||
access_token_keys = []
|
||||
access_token_values_list = [await request.app.state.redis.get(key) for key in access_token_keys]
|
||||
@@ -40,11 +40,11 @@ class OnlineService:
|
||||
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('login_info').get('ipaddr'):
|
||||
if query_object.user_name == payload.get('user_name'):
|
||||
online_info_list = [online_dict]
|
||||
break
|
||||
elif not query_object.user_name and query_object.ipaddr:
|
||||
if query_object.ipaddr == payload.get('ipaddr'):
|
||||
if query_object.ipaddr == payload.get('login_info').get('ipaddr'):
|
||||
online_info_list = [online_dict]
|
||||
break
|
||||
elif query_object.user_name and query_object.ipaddr:
|
||||
@@ -70,7 +70,7 @@ class OnlineService:
|
||||
if page_object.token_ids:
|
||||
token_id_list = page_object.token_ids.split(',')
|
||||
for token_id in token_id_list:
|
||||
await request.app.state.redis.delete(f"{RedisInitKeyConfig.ACCESS_TOKEN.key}:{token_id}")
|
||||
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为空')
|
||||
|
@@ -8,7 +8,7 @@ pandas==2.2.2
|
||||
passlib[bcrypt]==1.7.4
|
||||
Pillow==10.4.0
|
||||
psutil==6.0.0
|
||||
pydantic-validation-decorator==0.1.2
|
||||
pydantic-validation-decorator==0.1.4
|
||||
PyJWT[crypto]==2.8.0
|
||||
PyMySQL==1.1.1
|
||||
redis==5.0.7
|
||||
|
@@ -71,7 +71,7 @@ class PageUtil:
|
||||
paginated_data.append(row[0])
|
||||
else:
|
||||
paginated_data.append(row)
|
||||
has_next = True if math.ceil(len(paginated_data) / page_size) > page_num else False
|
||||
has_next = math.ceil(total / page_size) > page_num
|
||||
result = PageResponseModel(
|
||||
rows=CamelCaseUtil.transform_result(paginated_data),
|
||||
pageNum=page_num,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vfadmin",
|
||||
"version": "1.3.1",
|
||||
"version": "1.3.3",
|
||||
"description": "vfadmin管理系统",
|
||||
"author": "insistence",
|
||||
"license": "MIT",
|
||||
|
Reference in New Issue
Block a user