diff --git a/README.md b/README.md
index bf347a475d54fe35c57a37ad5cd5c7d4056a4947..5aa73da5c5be8540bcc77735896add0dd5d23107 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,18 @@
-Dash-FastAPI-Admin v1.0.10
+Dash-FastAPI-Admin v1.1.0
基于Dash+FastAPI前后端分离的纯Python快速开发框架
-
+
+
## 平台简介
Dash-FastAPI-Admin是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
diff --git a/dash-fastapi-backend/config/get_scheduler.py b/dash-fastapi-backend/config/get_scheduler.py
index 8ecad29f0957ce7efedf00da70cf7a2d05364a07..af1c6334349e84b3c1ed6b25b62dfae7bd0030df 100644
--- a/dash-fastapi-backend/config/get_scheduler.py
+++ b/dash-fastapi-backend/config/get_scheduler.py
@@ -20,11 +20,49 @@ class MyCronTrigger(CronTrigger):
@classmethod
def from_crontab(cls, expr, timezone=None):
values = expr.split()
- if len(values) != 7:
- raise ValueError('Wrong number of fields; got {}, expected 7'.format(len(values)))
+ if len(values) != 6 and len(values) != 7:
+ raise ValueError('Wrong number of fields; got {}, expected 6 or 7'.format(len(values)))
- return cls(second=values[0], minute=values[1], hour=values[2], day=values[3], month=values[4],
- day_of_week=values[5], year=values[6], timezone=timezone)
+ second = values[0]
+ minute = values[1]
+ hour = values[2]
+ if '?' in values[3]:
+ day = None
+ elif 'L' in values[5]:
+ day = f"last {values[5].replace('L', '')}"
+ elif 'W' in values[3]:
+ day = cls.__find_recent_workday(int(values[3].split('W')[0]))
+ else:
+ day = values[3].replace('L', 'last')
+ month = values[4]
+ if '?' in values[5] or 'L' in values[5]:
+ week = None
+ elif '#' in values[5]:
+ 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
+ return cls(second=second, minute=minute, hour=hour, day=day, month=month, week=week,
+ day_of_week=day_of_week, year=year, timezone=timezone)
+
+ @classmethod
+ def __find_recent_workday(cls, day):
+ now = datetime.now()
+ date = datetime(now.year, now.month, day)
+ if date.weekday() < 5:
+ 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
job_stores = {
diff --git a/dash-fastapi-backend/module_admin/dao/log_dao.py b/dash-fastapi-backend/module_admin/dao/log_dao.py
index 92d347d7640bd52cceb4a775e07b6c40c1c97463..c5ee91b234e4c9621038086943bb79ef643b9fd4 100644
--- a/dash-fastapi-backend/module_admin/dao/log_dao.py
+++ b/dash-fastapi-backend/module_admin/dao/log_dao.py
@@ -1,3 +1,4 @@
+from sqlalchemy import asc, desc
from sqlalchemy.orm import Session
from module_admin.entity.do.log_do import SysOperLog, SysLogininfor
from module_admin.entity.vo.log_vo import OperLogModel, LogininforModel, OperLogQueryModel, LoginLogQueryModel
@@ -32,6 +33,12 @@ class OperationLogDao:
:param query_object: 查询参数对象
:return: 操作日志列表信息对象
"""
+ if query_object.is_asc == 'ascend':
+ order_by_column = asc(getattr(SysOperLog, query_object.order_by_column, None))
+ elif query_object.is_asc == 'descend':
+ order_by_column = desc(getattr(SysOperLog, query_object.order_by_column, None))
+ else:
+ order_by_column = asc(SysOperLog.oper_time)
operation_log_list = db.query(SysOperLog) \
.filter(SysOperLog.title.like(f'%{query_object.title}%') if query_object.title else True,
SysOperLog.oper_name.like(f'%{query_object.oper_name}%') if query_object.oper_name else True,
@@ -42,7 +49,7 @@ class OperationLogDao:
datetime.combine(datetime.strptime(query_object.oper_time_end, '%Y-%m-%d'), time(23, 59, 59)))
if query_object.oper_time_start and query_object.oper_time_end else True
)\
- .distinct().all()
+ .distinct().order_by(order_by_column).all()
return list_format_datetime(operation_log_list)
@@ -96,6 +103,12 @@ class LoginLogDao:
:param query_object: 查询参数对象
:return: 登录日志列表信息对象
"""
+ if query_object.is_asc == 'ascend':
+ order_by_column = asc(getattr(SysLogininfor, query_object.order_by_column, None))
+ elif query_object.is_asc == 'descend':
+ order_by_column = desc(getattr(SysLogininfor, query_object.order_by_column, None))
+ else:
+ order_by_column = asc(SysLogininfor.login_time)
login_log_list = db.query(SysLogininfor) \
.filter(SysLogininfor.ipaddr.like(f'%{query_object.ipaddr}%') if query_object.ipaddr else True,
SysLogininfor.user_name.like(f'%{query_object.user_name}%') if query_object.user_name else True,
@@ -105,7 +118,7 @@ class LoginLogDao:
datetime.combine(datetime.strptime(query_object.login_time_end, '%Y-%m-%d'), time(23, 59, 59)))
if query_object.login_time_start and query_object.login_time_end else True
)\
- .distinct().all()
+ .distinct().order_by(order_by_column).all()
return list_format_datetime(login_log_list)
diff --git a/dash-fastapi-backend/module_admin/entity/vo/log_vo.py b/dash-fastapi-backend/module_admin/entity/vo/log_vo.py
index 64a999ec1c22b7f7b50589288bb33cf2efceb8ed..a8486e230cf196e63f270bfdbd9894815596d764 100644
--- a/dash-fastapi-backend/module_admin/entity/vo/log_vo.py
+++ b/dash-fastapi-backend/module_admin/entity/vo/log_vo.py
@@ -50,6 +50,8 @@ class OperLogQueryModel(OperLogModel):
"""
操作日志管理不分页查询模型
"""
+ order_by_column: Optional[str]
+ is_asc: Optional[str]
oper_time_start: Optional[str]
oper_time_end: Optional[str]
@@ -91,6 +93,8 @@ class LoginLogQueryModel(LogininforModel):
"""
登录日志管理不分页查询模型
"""
+ order_by_column: Optional[str]
+ is_asc: Optional[str]
login_time_start: Optional[str]
login_time_end: Optional[str]
diff --git a/dash-fastapi-backend/sql/dash-fastapi.sql b/dash-fastapi-backend/sql/dash-fastapi.sql
index 2699e7e2243d12a68681e6c880611399b4026015..8514d9d9e9a46a1430161247524025d6d49cce21 100644
--- a/dash-fastapi-backend/sql/dash-fastapi.sql
+++ b/dash-fastapi-backend/sql/dash-fastapi.sql
@@ -260,9 +260,9 @@ CREATE TABLE `sys_job` (
-- ----------------------------
-- Records of sys_job
-- ----------------------------
-INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'default', 'default', 'module_task.scheduler_test.job', 'test', NULL, '0/10 * * * * * *', '2', '0', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
-INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'sqlalchemy', 'default', 'module_task.scheduler_test.job', 'new', '{\"test\": 111}', '0/15 * * * * * *', '1', '1', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
-INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'redis', 'default', 'module_task.scheduler_test.job', NULL, NULL, '0/20 * * * * * *', '3', '1', '1', 'admin', '2023-05-23 16:13:34', '', NULL, '');
+INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'default', 'default', 'module_task.scheduler_test.job', 'test', NULL, '0/10 * * * * ?', '2', '0', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
+INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'sqlalchemy', 'default', 'module_task.scheduler_test.job', 'new', '{\"test\": 111}', '0/15 * * * * ?', '1', '1', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
+INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'redis', 'default', 'module_task.scheduler_test.job', NULL, NULL, '0/20 * * * * ?', '3', '1', '1', 'admin', '2023-05-23 16:13:34', '', NULL, '');
-- ----------------------------
-- Table structure for sys_job_log
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py b/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
index 1971c5b6cefd2bf0161c209c2b1c7645b76a4d97..4cec7c0e3cfdf899a6ee94b089939fed9482a831 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
@@ -21,6 +21,7 @@ from api.log import get_login_log_list_api, delete_login_log_api, clear_login_lo
inputs=dict(
search_click=Input('login_log-search', 'nClicks'),
refresh_click=Input('login_log-refresh', 'nClicks'),
+ sorter=Input('login_log-list-table', 'sorter'),
pagination=Input('login_log-list-table', 'pagination'),
operations=Input('login_log-operations-store', 'data')
),
@@ -33,7 +34,7 @@ from api.log import get_login_log_list_api, delete_login_log_api, clear_login_lo
),
prevent_initial_call=True
)
-def get_login_log_table_data(search_click, refresh_click, pagination, operations, ipaddr, user_name, status_select, login_time_range, button_perms):
+def get_login_log_table_data(search_click, refresh_click, sorter, pagination, operations, ipaddr, user_name, status_select, login_time_range, button_perms):
"""
获取登录日志表格数据回调(进行表格相关增删查改操作后均会触发此回调)
"""
@@ -49,17 +50,21 @@ def get_login_log_table_data(search_click, refresh_click, pagination, operations
status=status_select,
login_time_start=login_time_start,
login_time_end=login_time_end,
+ order_by_column=sorter.get('columns')[0] if sorter else None,
+ is_asc=sorter.get('orders')[0] if sorter else None,
page_num=1,
page_size=10
)
- triggered_id = dash.ctx.triggered_id
- if triggered_id == 'login_log-list-table':
+ triggered_prop = dash.ctx.triggered[0].get('prop_id')
+ if triggered_prop == 'login_log-list-table.pagination':
query_params = dict(
ipaddr=ipaddr,
user_name=user_name,
status=status_select,
login_time_start=login_time_start,
login_time_end=login_time_end,
+ order_by_column=sorter.get('columns')[0] if sorter else None,
+ is_asc=sorter.get('orders')[0] if sorter else None,
page_num=pagination['current'],
page_size=pagination['pageSize']
)
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py b/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py
index 4bd6aa333bbd2493a8d69c07fb35f9b3a9527cf9..b1e6252502f2fb05d5b169e5dc72e5932de13762 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py
@@ -23,6 +23,7 @@ from api.dict import query_dict_data_list_api
inputs=dict(
search_click=Input('operation_log-search', 'nClicks'),
refresh_click=Input('operation_log-refresh', 'nClicks'),
+ sorter=Input('operation_log-list-table', 'sorter'),
pagination=Input('operation_log-list-table', 'pagination'),
operations=Input('operation_log-operations-store', 'data')
),
@@ -36,7 +37,7 @@ from api.dict import query_dict_data_list_api
),
prevent_initial_call=True
)
-def get_operation_log_table_data(search_click, refresh_click, pagination, operations, title, oper_name, business_type, status_select, oper_time_range, button_perms):
+def get_operation_log_table_data(search_click, refresh_click, sorter, pagination, operations, title, oper_name, business_type, status_select, oper_time_range, button_perms):
"""
获取操作日志表格数据回调(进行表格相关增删查改操作后均会触发此回调)
"""
@@ -53,11 +54,13 @@ def get_operation_log_table_data(search_click, refresh_click, pagination, operat
status=status_select,
oper_time_start=oper_time_start,
oper_time_end=oper_time_end,
+ order_by_column=sorter.get('columns')[0] if sorter else None,
+ is_asc=sorter.get('orders')[0] if sorter else None,
page_num=1,
page_size=10
)
- triggered_id = dash.ctx.triggered_id
- if triggered_id == 'operation_log-list-table':
+ triggered_prop = dash.ctx.triggered[0].get('prop_id')
+ if triggered_prop == 'operation_log-list-table.pagination':
query_params = dict(
title=title,
oper_name=oper_name,
@@ -65,6 +68,8 @@ def get_operation_log_table_data(search_click, refresh_click, pagination, operat
status=status_select,
oper_time_start=oper_time_start,
oper_time_end=oper_time_end,
+ order_by_column=sorter.get('columns')[0] if sorter else None,
+ is_asc=sorter.get('orders')[0] if sorter else None,
page_num=pagination['current'],
page_size=pagination['pageSize']
)
diff --git a/dash-fastapi-frontend/views/monitor/logininfor/__init__.py b/dash-fastapi-frontend/views/monitor/logininfor/__init__.py
index bff7d37cd0273ec25f35d8c0965d6d5f418d7a03..55c9b37e6c0c1d1b07aa710c9fa8f14fd06cec9e 100644
--- a/dash-fastapi-frontend/views/monitor/logininfor/__init__.py
+++ b/dash-fastapi-frontend/views/monitor/logininfor/__init__.py
@@ -331,6 +331,10 @@ def render(button_perms):
rowSelectionType='checkbox',
rowSelectionWidth=50,
bordered=True,
+ sortOptions={
+ 'sortDataIndexes': ['user_name', 'login_time'],
+ 'multiple': False
+ },
pagination={
'pageSize': page_size,
'current': page_num,
diff --git a/dash-fastapi-frontend/views/monitor/operlog/__init__.py b/dash-fastapi-frontend/views/monitor/operlog/__init__.py
index 1ee38e09230b26e8d9018f62b1d461d508218fa1..8c1f3a7c0604a06c2d8578dedb57eb1e5779ab63 100644
--- a/dash-fastapi-frontend/views/monitor/operlog/__init__.py
+++ b/dash-fastapi-frontend/views/monitor/operlog/__init__.py
@@ -361,6 +361,10 @@ def render(button_perms):
rowSelectionType='checkbox',
rowSelectionWidth=50,
bordered=True,
+ sortOptions={
+ 'sortDataIndexes': ['oper_name', 'oper_time'],
+ 'multiple': False
+ },
pagination={
'pageSize': page_size,
'current': page_num,
diff --git a/requirements.txt b/requirements.txt
index 41f8638b70b399a0eefae1f1880c05f704ac8835..dfbeb623ec2bcda7d640dff8bc6da4d0dcc3d5f1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -17,7 +17,7 @@ psutil==5.9.5
PyMySQL==1.0.3
python-jose[cryptography]==3.3.0
redis==5.0.1
-requests==2.30.0
+requests==2.31.0
SQLAlchemy==1.4.48
user-agents==2.2.0
waitress==2.1.2