diff --git a/README.md b/README.md index bf347a475d54fe35c57a37ad5cd5c7d4056a4947..5aa73da5c5be8540bcc77735896add0dd5d23107 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,18 @@

logo

-

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