diff --git a/README.md b/README.md
index 04caeaf93172d3348f20f14339521216b4f0e728..4420359665d82aafccb5643ef792d64a99249c52 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-Dash-FastAPI-Admin v1.0.4
+Dash-FastAPI-Admin v1.0.5
基于Dash+FastAPI前后端分离的纯Python快速开发框架
-
+
@@ -130,10 +130,14 @@ python3 app.py
```
## 交流与赞助
-如果有对本项目及FastAPI感兴趣的朋友,欢迎加入知识星球一起交流学习,让我们一起变得更强。如果你觉得这个项目帮助到了你,你可以请作者喝杯咖啡表示鼓励☕。
+如果有对本项目及FastAPI感兴趣的朋友,欢迎加入知识星球一起交流学习,让我们一起变得更强。如果你觉得这个项目帮助到了你,你可以请作者喝杯咖啡表示鼓励☕。扫描下面微信二维码添加微信备注DF-Admin即可进群,也欢迎大家加入dash大神费弗里的知识星球学习更多dash开发知识。
\ No newline at end of file
diff --git a/dash-fastapi-backend/module_admin/dao/dept_dao.py b/dash-fastapi-backend/module_admin/dao/dept_dao.py
index e08f85922ee4185da1a0ddcd16855452c111df34..dc5098d57a05d03f28288541298b4ca4da44d860 100644
--- a/dash-fastapi-backend/module_admin/dao/dept_dao.py
+++ b/dash-fastapi-backend/module_admin/dao/dept_dao.py
@@ -197,7 +197,7 @@ class DeptDao:
"""
db_dept = SysDept(**dept.dict())
db.add(db_dept)
- db.refresh(db_dept) # 刷新
+ db.flush()
return db_dept
diff --git a/dash-fastapi-backend/module_admin/service/job_service.py b/dash-fastapi-backend/module_admin/service/job_service.py
index 571c18fa861125c770cbbf1a0f04a10904a55049..5f50e8cf61b90363b0e07c38409b7e9a94350073 100644
--- a/dash-fastapi-backend/module_admin/service/job_service.py
+++ b/dash-fastapi-backend/module_admin/service/job_service.py
@@ -167,7 +167,7 @@ class JobService:
data = [JobModel(**vars(row)).dict() for row in job_list]
job_group_list = await DictDataService.query_dict_data_list_from_cache_services(request.app.state.redis, dict_type='sys_job_group')
- job_group_option = [dict(label=item.dict_label, value=item.dict_value) for item in job_group_list]
+ job_group_option = [dict(label=item.get('dict_label'), value=item.get('dict_value')) for item in job_group_list]
job_group_option_dict = {item.get('value'): item for item in job_group_option}
for item in data:
diff --git a/dash-fastapi-frontend/app.py b/dash-fastapi-frontend/app.py
index dd9d815c9b4872028ca9f1165d584d6a0d3b8966..cf8cd500fd759cbab61a0753e82b7c8ee5fc3c6a 100644
--- a/dash-fastapi-frontend/app.py
+++ b/dash-fastapi-frontend/app.py
@@ -76,20 +76,27 @@ app.layout = html.Div(
@app.callback(
- [Output('app-mount', 'children'),
- Output('redirect-container', 'children', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('current-key-container', 'data'),
- Output('menu-info-store-container', 'data'),
- Output('menu-list-store-container', 'data'),
- Output('search-panel', 'data')],
- Input('url-container', 'pathname'),
- [State('url-container', 'trigger'),
- State('token-container', 'data')],
+ output=dict(
+ app_mount=Output('app-mount', 'children'),
+ redirect_container=Output('redirect-container', 'children', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ menu_current_key=Output('current-key-container', 'data'),
+ menu_info=Output('menu-info-store-container', 'data'),
+ menu_list=Output('menu-list-store-container', 'data'),
+ search_panel_data=Output('search-panel', 'data')
+ ),
+ inputs=dict(pathname=Input('url-container', 'pathname')),
+ state=dict(
+ url_trigger=State('url-container', 'trigger'),
+ session_token=State('token-container', 'data')
+ ),
prevent_initial_call=True
)
-def router(pathname, trigger, session_token):
+def router(pathname, url_trigger, session_token):
+ """
+ 全局路由回调
+ """
# 检查当前会话是否已经登录
token_result = session.get('Authorization')
# 若已登录
@@ -115,142 +122,136 @@ def router(pathname, trigger, session_token):
current_key = '首页'
if pathname == '/user/profile':
current_key = '个人资料'
- if trigger == 'load':
+ if url_trigger == 'load':
# 根据pathname控制渲染行为
if pathname == '/login' or pathname == '/forget':
# 重定向到主页面
- return [
- dash.no_update,
- dcc.Location(
- pathname='/',
- id='router-redirect'
- ),
- None,
- {'timestamp': time.time()},
- {'current_key': current_key},
- {'menu_info': menu_info},
- {'menu_list': menu_list},
- search_panel_data
- ]
+ return dict(
+ app_mount=dash.no_update,
+ redirect_container=dcc.Location(pathname='/', id='router-redirect'),
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key={'current_key': current_key},
+ menu_info={'menu_info': menu_info},
+ menu_list={'menu_list': menu_list},
+ search_panel_data=search_panel_data
+ )
# 否则正常渲染主页面
- return [
- views.layout.render_content(user_menu_info),
- None,
- fuc.FefferyFancyNotification('进入主页面', type='success', autoClose=2000),
- {'timestamp': time.time()},
- {'current_key': current_key},
- {'menu_info': menu_info},
- {'menu_list': menu_list},
- search_panel_data
- ]
+ return dict(
+ app_mount=views.layout.render_content(user_menu_info),
+ redirect_container=None,
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key={'current_key': current_key},
+ menu_info={'menu_info': menu_info},
+ menu_list={'menu_list': menu_list},
+ search_panel_data=search_panel_data
+ )
else:
- return [
- dash.no_update,
- None,
- None,
- {'timestamp': time.time()},
- {'current_key': current_key},
- {'menu_info': menu_info},
- {'menu_list': menu_list},
- search_panel_data
- ]
+ return dict(
+ app_mount=dash.no_update,
+ redirect_container=None,
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key={'current_key': current_key},
+ menu_info={'menu_info': menu_info},
+ menu_list={'menu_list': menu_list},
+ search_panel_data=search_panel_data
+ )
else:
# 渲染404状态页
- return [
- views.page_404.render_content(),
- None,
- None,
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=views.page_404.render_content(),
+ redirect_container=None,
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
else:
- return [
- dash.no_update,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=dash.no_update,
+ redirect_container=dash.no_update,
+ global_message_container=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
except Exception as e:
print(e)
- return [
- dash.no_update,
- None,
- fuc.FefferyFancyNotification('接口异常', type='error', autoClose=2000),
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=dash.no_update,
+ redirect_container=None,
+ global_message_container=fuc.FefferyFancyNotification('接口异常', type='error', autoClose=2000),
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
else:
# 若未登录
# 根据pathname控制渲染行为
# 检验pathname合法性
if pathname not in RouterConfig.BASIC_VALID_PATHNAME:
# 渲染404状态页
- return [
- views.page_404.render_content(),
- None,
- None,
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=views.page_404.render_content(),
+ redirect_container=None,
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
if pathname == '/login':
- return [
- views.login.render_content(),
- None,
- None,
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=views.login.render_content(),
+ redirect_container=None,
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
if pathname == '/forget':
- return [
- views.forget.render_forget_content(),
- None,
- None,
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=views.forget.render_forget_content(),
+ redirect_container=None,
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
# 否则重定向到登录页
- return [
- dash.no_update,
- dcc.Location(
- pathname='/login',
- id='router-redirect'
- ),
- None,
- {'timestamp': time.time()},
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update
- ]
+ return dict(
+ app_mount=dash.no_update,
+ redirect_container=dcc.Location(pathname='/login', id='router-redirect'),
+ global_message_container=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ menu_current_key=dash.no_update,
+ menu_info=dash.no_update,
+ menu_list=dash.no_update,
+ search_panel_data=dash.no_update
+ )
if __name__ == '__main__':
diff --git a/dash-fastapi-frontend/callbacks/forget_c.py b/dash-fastapi-frontend/callbacks/forget_c.py
index 9527ce35be12513999a61fe5d8f45e26913d3d7b..7b12a2bac2794f27515e672612eb52ce949a3d22 100644
--- a/dash-fastapi-frontend/callbacks/forget_c.py
+++ b/dash-fastapi-frontend/callbacks/forget_c.py
@@ -2,6 +2,7 @@ import dash
from dash import dcc
import feffery_utils_components as fuc
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
from server import app
from api.user import forget_user_pwd_api
@@ -9,26 +10,32 @@ from api.message import send_message_api
@app.callback(
- [Output('forget-username-form-item', 'validateStatus'),
- Output('forget-password-form-item', 'validateStatus'),
- Output('forget-password-again-form-item', 'validateStatus'),
- Output('forget-captcha-form-item', 'validateStatus'),
- Output('forget-username-form-item', 'help'),
- Output('forget-password-form-item', 'help'),
- Output('forget-password-again-form-item', 'help'),
- Output('forget-captcha-form-item', 'help'),
- Output('forget-submit', 'loading'),
- Output('redirect-container', 'children', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('forget-submit', 'nClicks'),
- [State('forget-username', 'value'),
- State('forget-password', 'value'),
- State('forget-password-again', 'value'),
- State('forget-input-captcha', 'value'),
- State('sms_code-session_id-container', 'data')],
+ output=dict(
+ username_form_status=Output('forget-username-form-item', 'validateStatus'),
+ password_form_status=Output('forget-password-form-item', 'validateStatus'),
+ password_again_form_status=Output('forget-password-again-form-item', 'validateStatus'),
+ captcha_form_status=Output('forget-captcha-form-item', 'validateStatus'),
+ username_form_help=Output('forget-username-form-item', 'help'),
+ password_form_help=Output('forget-password-form-item', 'help'),
+ password_again_form_help=Output('forget-password-again-form-item', 'help'),
+ captcha_form_help=Output('forget-captcha-form-item', 'help'),
+ submit_loading=Output('forget-submit', 'loading'),
+ redirect_container=Output('redirect-container', 'children', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ nClicks=Input('forget-submit', 'nClicks')
+ ),
+ state=dict(
+ username=State('forget-username', 'value'),
+ password=State('forget-password', 'value'),
+ password_again=State('forget-password-again', 'value'),
+ input_captcha=State('forget-input-captcha', 'value'),
+ session_id=State('sms_code-session_id-container', 'data')
+ ),
prevent_initial_call=True
)
-def login_auth(nClicks, username, password, password_again, input_captcha, session_id):
+def forget_auth(nClicks, username, password, password_again, input_captcha, session_id):
if nClicks:
# 校验全部输入值是否不为空
if all([username, password, password_again, input_captcha]):
@@ -39,84 +46,81 @@ def login_auth(nClicks, username, password, password_again, input_captcha, sessi
change_result = forget_user_pwd_api(forget_params)
if change_result.get('code') == 200:
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- True,
- dcc.Location(
- pathname='/login',
- id='forget-redirect'
- ),
- fuc.FefferyFancyMessage(change_result.get('message'), type='success')
- ]
+ return dict(
+ username_form_status=None,
+ password_form_status=None,
+ password_again_form_status=None,
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help=None,
+ password_again_form_help=None,
+ captcha_form_help=None,
+ submit_loading=False,
+ redirect_container=dcc.Location(pathname='/login', id='forget-redirect'),
+ global_message_container=fuc.FefferyFancyMessage(change_result.get('message'), type='success')
+ )
else:
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- None,
- fuc.FefferyFancyMessage(change_result.get('message'), type='error')
- ]
+ return dict(
+ username_form_status=None,
+ password_form_status=None,
+ password_again_form_status=None,
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help=None,
+ password_again_form_help=None,
+ captcha_form_help=None,
+ submit_loading=False,
+ redirect_container=None,
+ global_message_container=fuc.FefferyFancyMessage(change_result.get('message'), type='error')
+ )
except Exception as e:
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- None,
- fuc.FefferyFancyMessage(str(e), type='error')
- ]
+ return dict(
+ username_form_status=None,
+ password_form_status=None,
+ password_again_form_status=None,
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help=None,
+ password_again_form_help=None,
+ captcha_form_help=None,
+ submit_loading=False,
+ redirect_container=None,
+ global_message_container=fuc.FefferyFancyMessage(str(e), type='error')
+ )
else:
- return [
- None,
- 'error',
- 'error',
- None,
- None,
- '两次密码不一致',
- '两次密码不一致',
- None,
- False,
- None,
- None
- ]
-
- return [
- None if username else 'error',
- None if password else 'error',
- None if password_again else 'error',
- None if input_captcha else 'error',
- None if username else '请输入用户名!',
- None if password else '请输入新密码!',
- None if password_again else '请再次输入新密码!',
- None if input_captcha else '请输入短信验证码!',
- False,
- None,
- None
- ]
-
- return [dash.no_update] * 11
+ return dict(
+ username_form_status=None,
+ password_form_status='error',
+ password_again_form_status='error',
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help='两次密码不一致',
+ password_again_form_help='两次密码不一致',
+ captcha_form_help=None,
+ submit_loading=False,
+ redirect_container=None,
+ global_message_container=None
+ )
+
+ return dict(
+ username_form_status=None if username else 'error',
+ password_form_status=None if password else 'error',
+ password_again_form_status=None if password_again else 'error',
+ captcha_form_status=None if input_captcha else 'error',
+ username_form_help=None if username else '请输入用户名!',
+ password_form_help=None if password else '请输入新密码!',
+ password_again_form_help=None if password_again else '请再次输入新密码!',
+ captcha_form_help=None if input_captcha else '请输入短信验证码!',
+ submit_loading=False,
+ redirect_container=None,
+ global_message_container=None
+ )
+
+ raise PreventUpdate
@app.callback(
diff --git a/dash-fastapi-frontend/callbacks/layout_c/fold_side_menu.py b/dash-fastapi-frontend/callbacks/layout_c/fold_side_menu.py
index eed62bb0cf6da518285cd48260812ba8a365ca87..5096ca74a70aeeb16318bc93d035def67215acf1 100644
--- a/dash-fastapi-frontend/callbacks/layout_c/fold_side_menu.py
+++ b/dash-fastapi-frontend/callbacks/layout_c/fold_side_menu.py
@@ -3,6 +3,7 @@ from dash.dependencies import Input, Output, State
from server import app
+# 侧边栏折叠回调
app.clientside_callback(
'''
(nClicks, collapsed) => {
diff --git a/dash-fastapi-frontend/callbacks/login_c.py b/dash-fastapi-frontend/callbacks/login_c.py
index 465e1cfcc0206b24c0502b1c6358dcf3228b8245..d423bd013541e7b9a8c9f89fdefd9a2723265e7e 100644
--- a/dash-fastapi-frontend/callbacks/login_c.py
+++ b/dash-fastapi-frontend/callbacks/login_c.py
@@ -10,24 +10,30 @@ from api.login import login_api, get_captcha_image_api
@app.callback(
- [Output('login-username-form-item', 'validateStatus'),
- Output('login-password-form-item', 'validateStatus'),
- Output('login-captcha-form-item', 'validateStatus'),
- Output('login-username-form-item', 'help'),
- Output('login-password-form-item', 'help'),
- Output('login-captcha-form-item', 'help'),
- Output('login-captcha-image-container', 'n_clicks'),
- Output('login-submit', 'loading'),
- Output('token-container', 'data'),
- Output('redirect-container', 'children', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('login-submit', 'nClicks'),
- [State('login-username', 'value'),
- State('login-password', 'value'),
- State('login-captcha', 'value'),
- State('captcha_image-session_id-container', 'data'),
- State('login-captcha-image-container', 'n_clicks'),
- State('captcha-row-container', 'hidden')],
+ output=dict(
+ username_form_status=Output('login-username-form-item', 'validateStatus'),
+ password_form_status=Output('login-password-form-item', 'validateStatus'),
+ captcha_form_status=Output('login-captcha-form-item', 'validateStatus'),
+ username_form_help=Output('login-username-form-item', 'help'),
+ password_form_help=Output('login-password-form-item', 'help'),
+ captcha_form_help=Output('login-captcha-form-item', 'help'),
+ image_click=Output('login-captcha-image-container', 'n_clicks'),
+ submit_loading=Output('login-submit', 'loading'),
+ token=Output('token-container', 'data'),
+ redirect_container=Output('redirect-container', 'children', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ nClicks=Input('login-submit', 'nClicks')
+ ),
+ state=dict(
+ username=State('login-username', 'value'),
+ password=State('login-password', 'value'),
+ input_captcha=State('login-captcha', 'value'),
+ session_id=State('captcha_image-session_id-container', 'data'),
+ image_click=State('login-captcha-image-container', 'n_clicks'),
+ captcha_hidden=State('captcha-row-container', 'hidden')
+ ),
prevent_initial_call=True
)
def login_auth(nClicks, username, password, input_captcha, session_id, image_click, captcha_hidden):
@@ -43,70 +49,78 @@ def login_auth(nClicks, username, password, input_captcha, session_id, image_cli
if userinfo_result['code'] == 200:
token = userinfo_result['data']['access_token']
session['Authorization'] = token
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- False,
- token,
- dcc.Location(
- pathname='/',
- id='login-redirect'
- ),
- fuc.FefferyFancyMessage('登录成功', type='success'),
- ]
+ return dict(
+ username_form_status=None,
+ password_form_status=None,
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help=None,
+ captcha_form_help=None,
+ image_click=dash.no_update,
+ submit_loading=False,
+ token=token,
+ redirect_container=dcc.Location(pathname='/', id='login-redirect'),
+ global_message_container=fuc.FefferyFancyMessage('登录成功', type='success')
+ )
else:
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- image_click + 1,
- False,
- None,
- None,
- fuc.FefferyFancyMessage(userinfo_result.get('message'), type='error'),
- ]
+ return dict(
+ username_form_status=None,
+ password_form_status=None,
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help=None,
+ captcha_form_help=None,
+ image_click=image_click + 1,
+ submit_loading=False,
+ token=None,
+ redirect_container=None,
+ global_message_container=fuc.FefferyFancyMessage(userinfo_result.get('message'), type='error')
+ )
except Exception as e:
print(e)
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- image_click + 1,
- False,
- None,
- None,
- fuc.FefferyFancyMessage('接口异常', type='error'),
- ]
-
- return [
- None if username else 'error',
- None if password else 'error',
- None if input_captcha else 'error',
- None if username else '请输入用户名!',
- None if password else '请输入密码!',
- None if input_captcha else '请输入验证码!',
- dash.no_update,
- False,
- None,
- None,
- None
- ]
-
- return [dash.no_update] * 6 + [image_click + 1] + [dash.no_update] * 4
+ return dict(
+ username_form_status=None,
+ password_form_status=None,
+ captcha_form_status=None,
+ username_form_help=None,
+ password_form_help=None,
+ captcha_form_help=None,
+ image_click=image_click + 1,
+ submit_loading=False,
+ token=None,
+ redirect_container=None,
+ global_message_container=fuc.FefferyFancyMessage('接口异常', type='error')
+ )
+
+ return dict(
+ username_form_status=None if username else 'error',
+ password_form_status=None if password else 'error',
+ captcha_form_status=None if input_captcha else 'error',
+ username_form_help=None if username else '请输入用户名!',
+ password_form_help=None if password else '请输入密码!',
+ captcha_form_help=None if input_captcha else '请输入验证码!',
+ image_click=dash.no_update,
+ submit_loading=False,
+ token=None,
+ redirect_container=None,
+ global_message_container=None
+ )
+
+ return dict(
+ username_form_status=dash.no_update,
+ password_form_status=dash.no_update,
+ captcha_form_status=dash.no_update,
+ username_form_help=dash.no_update,
+ password_form_help=dash.no_update,
+ captcha_form_help=dash.no_update,
+ image_click=image_click + 1,
+ submit_loading=dash.no_update,
+ token=dash.no_update,
+ redirect_container=dash.no_update,
+ global_message_container=dash.no_update
+ )
@app.callback(
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/cache_c/control_c.py b/dash-fastapi-frontend/callbacks/monitor_c/cache_c/control_c.py
index 16afc774249ff0219976acba4db15d0548f98d1b..d73509237ac95c4d68f3bb7a5aa1e232ec9d2351 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/cache_c/control_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/cache_c/control_c.py
@@ -3,6 +3,7 @@ from dash.dependencies import Input, Output, State, ClientsideFunction
from server import app
+# 初始化echarts图表数据
app.clientside_callback(
'''
(n_intervals, data) => {
@@ -17,6 +18,7 @@ app.clientside_callback(
)
+# 渲染命令统计图表
app.clientside_callback(
ClientsideFunction(
namespace='clientside_command_stats',
@@ -27,6 +29,7 @@ app.clientside_callback(
)
+# 渲染内存信息统计图表
app.clientside_callback(
ClientsideFunction(
namespace='clientside_memory',
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_c.py b/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_c.py
index 21fbb84aab0b34389e98e65e45c7953802e38a43..d0eb60a8b0b65cfd8b93a78d6756769dc4ffda4d 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_c.py
@@ -4,6 +4,7 @@ import uuid
import json
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -12,23 +13,32 @@ from api.dict import query_dict_data_list_api
@app.callback(
- [Output('job-list-table', 'data', allow_duplicate=True),
- Output('job-list-table', 'pagination', allow_duplicate=True),
- Output('job-list-table', 'key'),
- Output('job-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('job-search', 'nClicks'),
- Input('job-refresh', 'nClicks'),
- Input('job-list-table', 'pagination'),
- Input('job-operations-store', 'data')],
- [State('job-job_name-input', 'value'),
- State('job-job_group-select', 'value'),
- State('job-status-select', 'value'),
- State('job-button-perms-container', 'data')],
+ output=dict(
+ job_table_data=Output('job-list-table', 'data', allow_duplicate=True),
+ job_table_pagination=Output('job-list-table', 'pagination', allow_duplicate=True),
+ job_table_key=Output('job-list-table', 'key'),
+ job_table_selectedrowkeys=Output('job-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('job-search', 'nClicks'),
+ refresh_click=Input('job-refresh', 'nClicks'),
+ pagination=Input('job-list-table', 'pagination'),
+ operations=Input('job-operations-store', 'data')
+ ),
+ state=dict(
+ job_name=State('job-job_name-input', 'value'),
+ job_group=State('job-job_group-select', 'value'),
+ status_select=State('job-status-select', 'value'),
+ button_perms=State('job-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_job_table_data(search_click, refresh_click, pagination, operations, job_name, job_group, status_select,
button_perms):
+ """
+ 获取定时任务表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
job_name=job_name,
job_group=job_group,
@@ -101,13 +111,26 @@ def get_job_table_data(search_click, refresh_click, pagination, operations, job_
} if 'monitor:job:query' in button_perms else None
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ job_table_data=table_data,
+ job_table_pagination=table_pagination,
+ job_table_key=str(uuid.uuid4()),
+ job_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ job_table_data=dash.no_update,
+ job_table_pagination=dash.no_update,
+ job_table_key=dash.no_update,
+ job_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置定时任务搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -126,6 +149,7 @@ app.clientside_callback(
)
+# 隐藏/显示定时任务搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -152,6 +176,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_job_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -162,7 +189,7 @@ def change_job_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -171,64 +198,77 @@ def change_job_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_job_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
- [Output('job-modal', 'visible', allow_duplicate=True),
- Output('job-modal', 'title'),
- Output('job-job_name', 'value'),
- Output('job-job_group', 'value'),
- Output('job-invoke_target', 'value'),
- Output('job-cron_expression', 'value'),
- Output('job-job_args', 'value'),
- Output('job-job_kwargs', 'value'),
- Output('job-misfire_policy', 'value'),
- Output('job-concurrent', 'value'),
- Output('job-status', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('job-edit-id-store', 'data'),
- Output('job-operations-store-bk', 'data')],
- [Input({'type': 'job-operation-button', 'index': ALL}, 'nClicks'),
- Input('job-list-table', 'nClicksDropdownItem')],
- [State('job-list-table', 'selectedRowKeys'),
- State('job-list-table', 'recentlyClickedDropdownItemTitle'),
- State('job-list-table', 'recentlyDropdownItemClickedRow')],
+ output=dict(
+ modal_visible=Output('job-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('job-modal', 'title'),
+ form_value=Output({'type': 'job-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'job-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'job-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('job-edit-id-store', 'data'),
+ modal_type=Output('job-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'job-operation-button', 'index': ALL}, 'nClicks'),
+ dropdown_click=Input('job-list-table', 'nClicksDropdownItem')
+ ),
+ state=dict(
+ selected_row_keys=State('job-list-table', 'selectedRowKeys'),
+ recently_clicked_dropdown_item_title=State('job-list-table', 'recentlyClickedDropdownItemTitle'),
+ recently_dropdown_item_clicked_row=State('job-list-table', 'recentlyDropdownItemClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_job_modal(operation_click, dropdown_click, selected_row_keys, recently_clicked_dropdown_item_title,
recently_dropdown_item_clicked_row):
+ """
+ 显示新增或编辑定时任务弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'job-operation-button'} \
or trigger_id == {'index': 'edit', 'type': 'job-operation-button'} \
or (trigger_id == 'job-list-table' and recently_clicked_dropdown_item_title == '修改'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
if trigger_id == {'index': 'add', 'type': 'job-operation-button'}:
- return [
- True,
- '新增任务',
- None,
- None,
- None,
- None,
- None,
- None,
- '1',
- '1',
- '0',
- dash.no_update,
- None,
- {'type': 'add'}
- ]
+ job_info = dict(
+ job_name=None,
+ job_group=None,
+ invoke_target=None,
+ cron_expression=None,
+ job_args=None,
+ job_kwargs=None,
+ misfire_policy='1',
+ concurrent='1',
+ status='0'
+ )
+ return dict(
+ modal_visible=True,
+ modal_title='新增任务',
+ form_value=[job_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger=dash.no_update,
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id == {'index': 'edit', 'type': 'job-operation-button'} or (trigger_id == 'job-list-table' and recently_clicked_dropdown_item_title == '修改'):
if trigger_id == {'index': 'edit', 'type': 'job-operation-button'}:
job_id = int(','.join(selected_row_keys))
@@ -237,125 +277,112 @@ def add_edit_job_modal(operation_click, dropdown_click, selected_row_keys, recen
job_info_res = get_job_detail_api(job_id=job_id)
if job_info_res['code'] == 200:
job_info = job_info_res['data']
- return [
- True,
- '编辑任务',
- job_info.get('job_name'),
- job_info.get('job_group'),
- job_info.get('invoke_target'),
- job_info.get('cron_expression'),
- job_info.get('job_args'),
- job_info.get('job_kwargs'),
- job_info.get('misfire_policy'),
- job_info.get('concurrent'),
- job_info.get('status'),
- {'timestamp': time.time()},
- job_info if job_info else None,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 11 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑任务',
+ form_value=[job_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=job_info if job_info else None,
+ modal_type={'type': 'edit'}
+ )
+
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
- return [dash.no_update] * 12 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('job-job_name-form-item', 'validateStatus'),
- Output('job-invoke_target-form-item', 'validateStatus'),
- Output('job-cron_expression-form-item', 'validateStatus'),
- Output('job-job_name-form-item', 'help'),
- Output('job-invoke_target-form-item', 'help'),
- Output('job-cron_expression-form-item', 'help'),
- Output('job-modal', 'visible'),
- Output('job-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('job-modal', 'okCounts'),
- [State('job-operations-store-bk', 'data'),
- State('job-edit-id-store', 'data'),
- State('job-job_name', 'value'),
- State('job-job_group', 'value'),
- State('job-invoke_target', 'value'),
- State('job-cron_expression', 'value'),
- State('job-job_args', 'value'),
- State('job-job_kwargs', 'value'),
- State('job-misfire_policy', 'value'),
- State('job-concurrent', 'value'),
- State('job-status', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'job-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'job-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('job-modal', 'visible'),
+ operations=Output('job-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('job-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('job-operations-store-bk', 'data'),
+ edit_row_info=State('job-edit-id-store', 'data'),
+ form_value=State({'type': 'job-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'job-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def job_confirm(confirm_trigger, operation_type, cur_job_info, job_name, job_group, invoke_target, cron_expression,
- job_args, job_kwargs, misfire_policy, concurrent, status):
+def job_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label):
+ """
+ 新增或编定时任务弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([job_name, invoke_target, cron_expression]):
- params_add = dict(job_name=job_name, job_group=job_group, invoke_target=invoke_target,
- cron_expression=cron_expression, job_args=job_args, job_kwargs=job_kwargs,
- misfire_policy=misfire_policy, concurrent=concurrent, status=status)
- params_edit = dict(job_id=cur_job_info.get('job_id') if cur_job_info else None, job_name=job_name,
- job_group=job_group, invoke_target=invoke_target, cron_expression=cron_expression,
- job_args=job_args, job_kwargs=job_kwargs,
- misfire_policy=misfire_policy, concurrent=concurrent, status=status)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params_add = form_value_state
+ params_edit = params_add.copy()
+ params_edit['job_id'] = edit_row_info.get('job_id') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_job_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_job_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [
- None if job_name else 'error',
- None if invoke_target else 'error',
- None if cron_expression else 'error',
- None if job_name else '请输入任务名称!',
- None if invoke_target else '请输入调用目标字符串!',
- None if cron_expression else '请输入cron执行表达式!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 10
+ raise PreventUpdate
@app.callback(
@@ -368,6 +395,9 @@ def job_confirm(confirm_trigger, operation_type, cur_job_info, job_name, job_gro
prevent_initial_call=True
)
def table_switch_job_status(recently_switch_data_index, recently_switch_status, recently_switch_row):
+ """
+ 表格内切换定时任务状态回调
+ """
if recently_switch_data_index:
if recently_switch_status:
params = dict(job_id=int(recently_switch_row['key']), status='0', type='status')
@@ -383,109 +413,89 @@ def table_switch_job_status(recently_switch_data_index, recently_switch_status,
]
return [
- dash.no_update,
+ {'type': 'switch-status'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('修改失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
- [Output('job_detail-modal', 'visible', allow_duplicate=True),
- Output('job_detail-modal', 'title'),
- Output('job_detail-job_name-text', 'children'),
- Output('job_detail-job_group-text', 'children'),
- Output('job_detail-job_executor-text', 'children'),
- Output('job_detail-invoke_target-text', 'children'),
- Output('job_detail-job_args-text', 'children'),
- Output('job_detail-job_kwargs-text', 'children'),
- Output('job_detail-cron_expression-text', 'children'),
- Output('job_detail-misfire_policy-text', 'children'),
- Output('job_detail-concurrent-text', 'children'),
- Output('job_detail-status-text', 'children'),
- Output('job_detail-create_time-text', 'children'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('job-list-table', 'nClicksDropdownItem'),
- [State('job-list-table', 'recentlyClickedDropdownItemTitle'),
- State('job-list-table', 'recentlyDropdownItemClickedRow')],
+ output=dict(
+ modal_visible=Output('job_detail-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('job_detail-modal', 'title'),
+ form_value=Output({'type': 'job_detail-form-value', 'index': ALL}, 'children'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ dropdown_click=Input('job-list-table', 'nClicksDropdownItem')
+ ),
+ state=dict(
+ recently_clicked_dropdown_item_title=State('job-list-table', 'recentlyClickedDropdownItemTitle'),
+ recently_dropdown_item_clicked_row=State('job-list-table', 'recentlyDropdownItemClickedRow')
+ ),
prevent_initial_call=True
)
def get_job_detail_modal(dropdown_click, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row):
+ """
+ 显示定时任务详情弹窗回调及执行一次定时任务回调
+ """
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[-3]]
+ # 显示定时任务详情弹窗
if dropdown_click and recently_clicked_dropdown_item_title == '任务详细':
job_id = int(recently_dropdown_item_clicked_row['key'])
job_info_res = get_job_detail_api(job_id=job_id)
if job_info_res['code'] == 200:
job_info = job_info_res['data']
if job_info.get('misfire_policy') == '1':
- misfire_policy = '立即执行'
+ job_info['misfire_policy'] = '立即执行'
elif job_info.get('misfire_policy') == '2':
- misfire_policy = '执行一次'
+ job_info['misfire_policy'] = '执行一次'
else:
- misfire_policy = '放弃执行'
- return [
- True,
- '任务详情',
- job_info.get('job_name'),
- job_info.get('job_group'),
- job_info.get('job_executor'),
- job_info.get('invoke_target'),
- job_info.get('job_args'),
- job_info.get('job_kwargs'),
- job_info.get('cron_expression'),
- misfire_policy,
- '是' if job_info.get('concurrent') == '0' else '否',
- '正常' if job_info.get('status') == '0' else '停用',
- job_info.get('create_time'),
- {'timestamp': time.time()},
- None
- ]
+ job_info['misfire_policy'] = '放弃执行'
+ job_info['concurrent'] = '是' if job_info.get('concurrent') == '0' else '否'
+ job_info['status'] = '正常' if job_info.get('status') == '0' else '停用'
+ return dict(
+ modal_visible=True,
+ modal_title='任务详情',
+ form_value=[job_info.get(k) for k in form_value_list],
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=None
+ )
- return [dash.no_update] * 13 + [{'timestamp': time.time()}, None]
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=None
+ )
+ # 执行一次定时任务
if dropdown_click and recently_clicked_dropdown_item_title == '执行一次':
job_id = int(recently_dropdown_item_clicked_row['key'])
job_info_res = execute_job_api(dict(job_id=job_id))
if job_info_res['code'] == 200:
+ return dict(
+ modal_visible=False,
+ modal_title=None,
+ form_value=[None] * len(form_value_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('执行成功', type='success')
+ )
- return [
- False,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('执行成功', type='success')
- ]
-
- return [
- False,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('执行失败', type='success')
- ]
+ return dict(
+ modal_visible=False,
+ modal_title=None,
+ form_value=[None] * len(form_value_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('执行失败', type='error')
+ )
- return [dash.no_update] * 15
+ raise PreventUpdate
@app.callback(
@@ -501,6 +511,9 @@ def get_job_detail_modal(dropdown_click, recently_clicked_dropdown_item_title, r
)
def job_delete_modal(operation_click, dropdown_click,
selected_row_keys, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row):
+ """
+ 显示删除定时任务二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'job-operation-button'} or (
trigger_id == 'job-list-table' and recently_clicked_dropdown_item_title == '删除'):
@@ -519,7 +532,7 @@ def job_delete_modal(operation_click, dropdown_click,
{'job_ids': job_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -531,6 +544,9 @@ def job_delete_modal(operation_click, dropdown_click,
prevent_initial_call=True
)
def job_delete_confirm(delete_confirm, job_ids_data):
+ """
+ 删除定时任务弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = job_ids_data
@@ -548,24 +564,33 @@ def job_delete_confirm(delete_confirm, job_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
- [Output('job_to_job_log-modal', 'visible'),
- Output('job_to_job_log-modal', 'title'),
- Output('job_log-job_name-input', 'value', allow_duplicate=True),
- Output('job_log-job_group-select', 'options'),
- Output('job_log-search', 'nClicks'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input({'type': 'job-operation-log', 'index': ALL}, 'nClicks'),
- Input('job-list-table', 'nClicksDropdownItem')],
- [State('job-list-table', 'recentlyClickedDropdownItemTitle'),
- State('job-list-table', 'recentlyDropdownItemClickedRow'),
- State('job_log-search', 'nClicks')],
+ output=dict(
+ job_log_modal_visible=Output('job_to_job_log-modal', 'visible'),
+ job_log_modal_title=Output('job_to_job_log-modal', 'title'),
+ job_log_job_name=Output('job_log-job_name-input', 'value', allow_duplicate=True),
+ job_log_job_group_options=Output('job_log-job_group-select', 'options'),
+ job_log_search_nclick=Output('job_log-search', 'nClicks'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'job-operation-log', 'index': ALL}, 'nClicks'),
+ dropdown_click=Input('job-list-table', 'nClicksDropdownItem')
+ ),
+ state=dict(
+ recently_clicked_dropdown_item_title=State('job-list-table', 'recentlyClickedDropdownItemTitle'),
+ recently_dropdown_item_clicked_row=State('job-list-table', 'recentlyDropdownItemClickedRow'),
+ job_log_search_nclick=State('job_log-search', 'nClicks')
+ ),
prevent_initial_call=True
)
def job_to_job_log_modal(operation_click, dropdown_click, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row, job_log_search_nclick):
+ """
+ 显示定时任务对应调度日志表格弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'log', 'type': 'job-operation-log'} or (trigger_id == 'job-list-table' and recently_clicked_dropdown_item_title == '调度日志'):
@@ -576,25 +601,25 @@ def job_to_job_log_modal(operation_click, dropdown_click, recently_clicked_dropd
option_table = [dict(label=item.get('dict_label'), value=item.get('dict_value')) for item in data]
if trigger_id == 'job-list-table' and recently_clicked_dropdown_item_title == '调度日志':
- return [
- True,
- '任务调度日志',
- recently_dropdown_item_clicked_row.get('job_name'),
- option_table,
- job_log_search_nclick + 1 if job_log_search_nclick else 1,
- {'timestamp': time.time()},
- ]
-
- return [
- True,
- '任务调度日志',
- None,
- option_table,
- job_log_search_nclick + 1 if job_log_search_nclick else 1,
- {'timestamp': time.time()},
- ]
+ return dict(
+ job_log_modal_visible=True,
+ job_log_modal_title='任务调度日志',
+ job_log_job_name=recently_dropdown_item_clicked_row.get('job_name'),
+ job_log_job_group_options=option_table,
+ job_log_search_nclick=job_log_search_nclick + 1 if job_log_search_nclick else 1,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
+
+ return dict(
+ job_log_modal_visible=True,
+ job_log_modal_title='任务调度日志',
+ job_log_job_name=None,
+ job_log_job_group_options=option_table,
+ job_log_search_nclick=job_log_search_nclick + 1 if job_log_search_nclick else 1,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 6
+ raise PreventUpdate
@app.callback(
@@ -606,6 +631,9 @@ def job_to_job_log_modal(operation_click, dropdown_click, recently_clicked_dropd
prevent_initial_call=True
)
def export_job_list(export_click):
+ """
+ 导出定时任务信息回调
+ """
if export_click:
export_job_res = export_job_list_api({})
if export_job_res.status_code == 200:
@@ -625,7 +653,7 @@ def export_job_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -634,8 +662,11 @@ def export_job_list(export_click):
prevent_initial_call=True
)
def reset_job_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_log_c.py b/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_log_c.py
index 61e05408c0756495123169aac26ba1636d34b78b..7b827ac3bee4527dead485064278e7c161bfddcd 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_log_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/job_c/job_log_c.py
@@ -4,6 +4,7 @@ import uuid
import json
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -12,23 +13,32 @@ from api.dict import query_dict_data_list_api
@app.callback(
- [Output('job_log-list-table', 'data', allow_duplicate=True),
- Output('job_log-list-table', 'pagination', allow_duplicate=True),
- Output('job_log-list-table', 'key'),
- Output('job_log-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('job_log-search', 'nClicks'),
- Input('job_log-refresh', 'nClicks'),
- Input('job_log-list-table', 'pagination'),
- Input('job_log-operations-store', 'data')],
- [State('job_log-job_name-input', 'value'),
- State('job_log-job_group-select', 'value'),
- State('job_log-status-select', 'value'),
- State('job_log-create_time-range', 'value'),
- State('job_log-button-perms-container', 'data')],
+ output=dict(
+ job_log_table_data=Output('job_log-list-table', 'data', allow_duplicate=True),
+ job_log_table_pagination=Output('job_log-list-table', 'pagination', allow_duplicate=True),
+ job_log_table_key=Output('job_log-list-table', 'key'),
+ job_log_table_selectedrowkeys=Output('job_log-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('job_log-search', 'nClicks'),
+ refresh_click=Input('job_log-refresh', 'nClicks'),
+ pagination=Input('job_log-list-table', 'pagination'),
+ operations=Input('job_log-operations-store', 'data')
+ ),
+ state=dict(
+ job_name=State('job_log-job_name-input', 'value'),
+ job_group=State('job_log-job_group-select', 'value'),
+ status_select=State('job_log-status-select', 'value'),
+ create_time_range=State('job_log-create_time-range', 'value'),
+ button_perms=State('job_log-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_job_log_table_data(search_click, refresh_click, pagination, operations, job_name, job_group, status_select, create_time_range, button_perms):
+ """
+ 获取定时任务对应调度日志表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
create_time_start = None
create_time_end = None
@@ -93,13 +103,26 @@ def get_job_log_table_data(search_click, refresh_click, pagination, operations,
} if 'monitor:job:query' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ job_log_table_data=table_data,
+ job_log_table_pagination=table_pagination,
+ job_log_table_key=str(uuid.uuid4()),
+ job_log_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ job_log_table_data=dash.no_update,
+ job_log_table_pagination=dash.no_update,
+ job_log_table_key=dash.no_update,
+ job_log_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置定时任务调度日志搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -119,6 +142,7 @@ app.clientside_callback(
)
+# 隐藏/显示定时任务调度日志搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -140,51 +164,45 @@ app.clientside_callback(
@app.callback(
- [Output('job_log-modal', 'visible', allow_duplicate=True),
- Output('job_log-modal', 'title'),
- Output('job_log-job_name-text', 'children'),
- Output('job_log-job_group-text', 'children'),
- Output('job_log-job_executor-text', 'children'),
- Output('job_log-invoke_target-text', 'children'),
- Output('job_log-job_args-text', 'children'),
- Output('job_log-job_kwargs-text', 'children'),
- Output('job_log-job_trigger-text', 'children'),
- Output('job_log-job_message-text', 'children'),
- Output('job_log-status-text', 'children'),
- Output('job_log-create_time-text', 'children'),
- Output('job_log-exception_info-text', 'children'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- Input('job_log-list-table', 'nClicksButton'),
- [State('job_log-list-table', 'clickedContent'),
- State('job_log-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal_visible=Output('job_log-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('job_log-modal', 'title'),
+ form_value=Output({'type': 'job_log-form-value', 'index': ALL}, 'children'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ button_click=Input('job_log-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ clicked_content=State('job_log-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('job_log-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_job_log_modal(button_click, clicked_content, recently_button_clicked_row):
if button_click:
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[-2]]
job_log_id = int(recently_button_clicked_row['key'])
job_log_info_res = get_job_log_detail_api(job_log_id=job_log_id)
if job_log_info_res['code'] == 200:
job_log_info = job_log_info_res['data']
- return [
- True,
- '任务执行日志详情',
- job_log_info.get('job_name'),
- job_log_info.get('job_group'),
- job_log_info.get('job_executor'),
- job_log_info.get('invoke_target'),
- job_log_info.get('job_args'),
- job_log_info.get('job_kwargs'),
- job_log_info.get('job_trigger'),
- job_log_info.get('job_message'),
- '成功' if job_log_info.get('status') == '0' else '失败',
- job_log_info.get('create_time'),
- job_log_info.get('exception_info'),
- {'timestamp': time.time()},
- ]
+ job_log_info['status'] = '成功' if job_log_info.get('status') == '0' else '失败'
+ return dict(
+ modal_visible=True,
+ modal_title='任务执行日志详情',
+ form_value=[job_log_info.get(k) for k in form_value_list],
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 13 + [{'timestamp': time.time()}]
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 14
+ raise PreventUpdate
@app.callback(
@@ -193,17 +211,18 @@ def add_edit_job_log_modal(button_click, clicked_content, recently_button_clicke
prevent_initial_call=True
)
def change_job_log_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -215,6 +234,9 @@ def change_job_log_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def job_log_delete_modal(operation_click, selected_row_keys):
+ """
+ 显示删除或清空定时任务调度日志二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.index in ['delete', 'clear']:
if trigger_id.index == 'delete':
@@ -233,7 +255,7 @@ def job_log_delete_modal(operation_click, selected_row_keys):
{'oper_type': 'clear', 'job_log_ids': ''}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -245,6 +267,9 @@ def job_log_delete_modal(operation_click, selected_row_keys):
prevent_initial_call=True
)
def job_log_delete_confirm(delete_confirm, job_log_ids_data):
+ """
+ 删除或清空定时任务调度日志弹窗确认回调,实现删除或清空操作
+ """
if delete_confirm:
oper_type = job_log_ids_data.get('oper_type')
@@ -279,7 +304,7 @@ def job_log_delete_confirm(delete_confirm, job_log_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -291,6 +316,9 @@ def job_log_delete_confirm(delete_confirm, job_log_ids_data):
prevent_initial_call=True
)
def export_job_log_list(export_click):
+ """
+ 导出定时任务调度日志信息回调
+ """
if export_click:
export_job_log_res = export_job_log_list_api({})
if export_job_log_res.status_code == 200:
@@ -310,7 +338,7 @@ def export_job_log_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -319,9 +347,12 @@ def export_job_log_list(export_click):
prevent_initial_call=True
)
def reset_job_log_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py b/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
index 754ed98a6af7f6260c35d8e391ccc87659bad48b..1971c5b6cefd2bf0161c209c2b1c7645b76a4d97 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -10,23 +11,32 @@ from api.log import get_login_log_list_api, delete_login_log_api, clear_login_lo
@app.callback(
- [Output('login_log-list-table', 'data', allow_duplicate=True),
- Output('login_log-list-table', 'pagination', allow_duplicate=True),
- Output('login_log-list-table', 'key'),
- Output('login_log-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('login_log-search', 'nClicks'),
- Input('login_log-refresh', 'nClicks'),
- Input('login_log-list-table', 'pagination'),
- Input('login_log-operations-store', 'data')],
- [State('login_log-ipaddr-input', 'value'),
- State('login_log-user_name-input', 'value'),
- State('login_log-status-select', 'value'),
- State('login_log-login_time-range', 'value'),
- State('login_log-button-perms-container', 'data')],
+ output=dict(
+ login_log_table_data=Output('login_log-list-table', 'data', allow_duplicate=True),
+ login_log_table_pagination=Output('login_log-list-table', 'pagination', allow_duplicate=True),
+ login_log_table_key=Output('login_log-list-table', 'key'),
+ login_log_table_selectedrowkeys=Output('login_log-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('login_log-search', 'nClicks'),
+ refresh_click=Input('login_log-refresh', 'nClicks'),
+ pagination=Input('login_log-list-table', 'pagination'),
+ operations=Input('login_log-operations-store', 'data')
+ ),
+ state=dict(
+ ipaddr=State('login_log-ipaddr-input', 'value'),
+ user_name=State('login_log-user_name-input', 'value'),
+ status_select=State('login_log-status-select', 'value'),
+ login_time_range=State('login_log-login_time-range', 'value'),
+ button_perms=State('login_log-button-perms-container', 'data')
+ ),
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):
+ """
+ 获取登录日志表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
login_time_start = None
login_time_end = None
@@ -72,13 +82,26 @@ def get_login_log_table_data(search_click, refresh_click, pagination, operations
item['status'] = dict(tag='失败', color='volcano')
item['key'] = str(item['info_id'])
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ login_log_table_data=table_data,
+ login_log_table_pagination=table_pagination,
+ login_log_table_key=str(uuid.uuid4()),
+ login_log_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ login_log_table_data=dash.no_update,
+ login_log_table_pagination=dash.no_update,
+ login_log_table_key=dash.no_update,
+ login_log_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置登录日志搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -98,6 +121,7 @@ app.clientside_callback(
)
+# 隐藏/显示登录日志搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -124,17 +148,18 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_login_log_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -143,6 +168,9 @@ def change_login_log_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_login_log_unlock_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制解锁按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -153,7 +181,7 @@ def change_login_log_unlock_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -165,6 +193,9 @@ def change_login_log_unlock_button_status(table_rows_selected):
prevent_initial_call=True
)
def login_log_delete_modal(operation_click, selected_row_keys):
+ """
+ 显示删除或清空登录日志二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.index in ['delete', 'clear']:
if trigger_id.index == 'delete':
@@ -183,7 +214,7 @@ def login_log_delete_modal(operation_click, selected_row_keys):
{'oper_type': 'clear', 'info_ids': ''}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -195,6 +226,9 @@ def login_log_delete_modal(operation_click, selected_row_keys):
prevent_initial_call=True
)
def login_log_delete_confirm(delete_confirm, info_ids_data):
+ """
+ 删除或清空登录日志弹窗确认回调,实现删除或清空操作
+ """
if delete_confirm:
oper_type = info_ids_data.get('oper_type')
@@ -229,7 +263,7 @@ def login_log_delete_confirm(delete_confirm, info_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -241,6 +275,9 @@ def login_log_delete_confirm(delete_confirm, info_ids_data):
prevent_initial_call=True
)
def export_login_log_list(export_click):
+ """
+ 导出登录日志信息回调
+ """
if export_click:
export_login_log_res = export_login_log_list_api({})
if export_login_log_res.status_code == 200:
@@ -260,7 +297,7 @@ def export_login_log_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -269,12 +306,15 @@ def export_login_log_list(export_click):
prevent_initial_call=True
)
def reset_login_log_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -285,6 +325,9 @@ def reset_login_log_export_status(data):
prevent_initial_call=True
)
def unlock_user(unlock_click, selected_rows):
+ """
+ 解锁用户回调
+ """
if unlock_click:
user_name = selected_rows[0].get('user_name')
unlock_info_res = unlock_user_api(dict(user_name=user_name))
@@ -300,4 +343,4 @@ def unlock_user(unlock_click, selected_rows):
fuc.FefferyFancyMessage('解锁失败', type='error')
]
- return [dash.no_update] * 2
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/online_c.py b/dash-fastapi-frontend/callbacks/monitor_c/online_c.py
index eacbc75d6f0fbeaf90d4dbe7bb1d7e3ffd06981a..8a63b4559e305ce66ef201bbca3d23d3b78b13a2 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/online_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/online_c.py
@@ -2,6 +2,7 @@ import dash
import time
import uuid
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -9,21 +10,30 @@ from api.online import get_online_list_api, force_logout_online_api, batch_logou
@app.callback(
- [Output('online-list-table', 'data', allow_duplicate=True),
- Output('online-list-table', 'pagination', allow_duplicate=True),
- Output('online-list-table', 'key'),
- Output('online-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('online-search', 'nClicks'),
- Input('online-refresh', 'nClicks'),
- Input('online-list-table', 'pagination'),
- Input('online-operations-store', 'data')],
- [State('online-ipaddr-input', 'value'),
- State('online-user_name-input', 'value'),
- State('online-button-perms-container', 'data')],
+ output=dict(
+ online_table_data=Output('online-list-table', 'data', allow_duplicate=True),
+ online_table_pagination=Output('online-list-table', 'pagination', allow_duplicate=True),
+ online_table_key=Output('online-list-table', 'key'),
+ online_table_selectedrowkeys=Output('online-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('online-search', 'nClicks'),
+ refresh_click=Input('online-refresh', 'nClicks'),
+ pagination=Input('online-list-table', 'pagination'),
+ operations=Input('online-operations-store', 'data')
+ ),
+ state=dict(
+ ipaddr=State('online-ipaddr-input', 'value'),
+ user_name=State('online-user_name-input', 'value'),
+ button_perms=State('online-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_online_table_data(search_click, refresh_click, pagination, operations, ipaddr, user_name, button_perms):
+ """
+ 获取在线用户表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
ipaddr=ipaddr,
user_name=user_name,
@@ -60,13 +70,26 @@ def get_online_table_data(search_click, refresh_click, pagination, operations, i
} if 'monitor:online:forceLogout' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ online_table_data=table_data,
+ online_table_pagination=table_pagination,
+ online_table_key=str(uuid.uuid4()),
+ online_table_selectedrowkeys=None,
+ api_check_token_trigger= {'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ online_table_data=dash.no_update,
+ online_table_pagination=dash.no_update,
+ online_table_key=dash.no_update,
+ online_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置在线用户搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -84,6 +107,7 @@ app.clientside_callback(
)
+# 隐藏/显示在线用户搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -110,6 +134,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_online_edit_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制批量强退按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -118,7 +145,7 @@ def change_online_edit_delete_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -134,6 +161,9 @@ def change_online_edit_delete_button_status(table_rows_selected):
)
def online_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示强退在线用户二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'online-operation-button'} or (
trigger_id == 'online-list-table' and clicked_content == '强退'):
@@ -154,7 +184,7 @@ def online_delete_modal(operation_click, button_click,
{'session_ids': session_ids, 'logout_type': logout_type}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -166,6 +196,9 @@ def online_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def online_delete_confirm(delete_confirm, session_ids_data):
+ """
+ 强退在线用户弹窗确认回调,实现强退操作
+ """
if delete_confirm:
params = dict(session_ids=session_ids_data.get('session_ids'))
@@ -187,4 +220,4 @@ def online_delete_confirm(delete_confirm, session_ids_data):
fuc.FefferyFancyMessage('强退失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py b/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py
index e45503f1516463adee6e65d531a56b15eaf3e180..4bd6aa333bbd2493a8d69c07fb35f9b3a9527cf9 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/operlog_c.py
@@ -4,6 +4,7 @@ import uuid
import json
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -12,24 +13,33 @@ from api.dict import query_dict_data_list_api
@app.callback(
- [Output('operation_log-list-table', 'data', allow_duplicate=True),
- Output('operation_log-list-table', 'pagination', allow_duplicate=True),
- Output('operation_log-list-table', 'key'),
- Output('operation_log-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('operation_log-search', 'nClicks'),
- Input('operation_log-refresh', 'nClicks'),
- Input('operation_log-list-table', 'pagination'),
- Input('operation_log-operations-store', 'data')],
- [State('operation_log-title-input', 'value'),
- State('operation_log-oper_name-input', 'value'),
- State('operation_log-business_type-select', 'value'),
- State('operation_log-status-select', 'value'),
- State('operation_log-oper_time-range', 'value'),
- State('operation_log-button-perms-container', 'data')],
+ output=dict(
+ operation_log_table_data=Output('operation_log-list-table', 'data', allow_duplicate=True),
+ operation_log_table_pagination=Output('operation_log-list-table', 'pagination', allow_duplicate=True),
+ operation_log_table_key=Output('operation_log-list-table', 'key'),
+ operation_log_table_selectedrowkeys=Output('operation_log-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('operation_log-search', 'nClicks'),
+ refresh_click=Input('operation_log-refresh', 'nClicks'),
+ pagination=Input('operation_log-list-table', 'pagination'),
+ operations=Input('operation_log-operations-store', 'data')
+ ),
+ state=dict(
+ title=State('operation_log-title-input', 'value'),
+ oper_name=State('operation_log-oper_name-input', 'value'),
+ business_type=State('operation_log-business_type-select', 'value'),
+ status_select=State('operation_log-status-select', 'value'),
+ oper_time_range=State('operation_log-oper_time-range', 'value'),
+ button_perms=State('operation_log-button-perms-container', 'data')
+ ),
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):
+ """
+ 获取操作日志表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
oper_time_start = None
oper_time_end = None
@@ -97,13 +107,26 @@ def get_operation_log_table_data(search_click, refresh_click, pagination, operat
} if 'monitor:operlog:query' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ operation_log_table_data=table_data,
+ operation_log_table_pagination=table_pagination,
+ operation_log_table_key=str(uuid.uuid4()),
+ operation_log_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ operation_log_table_data=dash.no_update,
+ operation_log_table_pagination=dash.no_update,
+ operation_log_table_key=dash.no_update,
+ operation_log_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置操作日志搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -124,6 +147,7 @@ app.clientside_callback(
)
+# 隐藏/显示操作日志搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -145,26 +169,28 @@ app.clientside_callback(
@app.callback(
- [Output('operation_log-modal', 'visible', allow_duplicate=True),
- Output('operation_log-modal', 'title'),
- Output('operation_log-title-text', 'children'),
- Output('operation_log-oper_url-text', 'children'),
- Output('operation_log-login_info-text', 'children'),
- Output('operation_log-request_method-text', 'children'),
- Output('operation_log-method-text', 'children'),
- Output('operation_log-oper_param-text', 'children'),
- Output('operation_log-json_result-text', 'children'),
- Output('operation_log-status-text', 'children'),
- Output('operation_log-cost_time-text', 'children'),
- Output('operation_log-oper_time-text', 'children'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- Input('operation_log-list-table', 'nClicksButton'),
- [State('operation_log-list-table', 'clickedContent'),
- State('operation_log-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal_visible=Output('operation_log-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('operation_log-modal', 'title'),
+ form_value=Output({'type': 'operation_log-form-value', 'index': ALL}, 'children'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ button_click=Input('operation_log-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ clicked_content=State('operation_log-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('operation_log-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_operation_log_modal(button_click, clicked_content, recently_button_clicked_row):
+ """
+ 显示操作日志详情弹窗回调
+ """
if button_click:
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[-2]]
oper_id = int(recently_button_clicked_row['key'])
operation_log_info_res = get_operation_log_detail_api(oper_id=oper_id)
if operation_log_info_res['code'] == 200:
@@ -172,26 +198,24 @@ def add_edit_operation_log_modal(button_click, clicked_content, recently_button_
oper_name = operation_log_info.get('oper_name') if operation_log_info.get('oper_name') else ''
oper_ip = operation_log_info.get('oper_ip') if operation_log_info.get('oper_ip') else ''
oper_location = operation_log_info.get('oper_location') if operation_log_info.get('oper_location') else ''
- login_info = f'{oper_name} / {oper_ip} / {oper_location}'
- return [
- True,
- '操作日志详情',
- operation_log_info.get('title'),
- operation_log_info.get('oper_url'),
- login_info,
- operation_log_info.get('request_method'),
- operation_log_info.get('method'),
- operation_log_info.get('oper_param'),
- operation_log_info.get('json_result'),
- '正常' if operation_log_info.get('status') == 0 else '失败',
- f"{operation_log_info.get('cost_time')}毫秒",
- operation_log_info.get('oper_time'),
- {'timestamp': time.time()},
- ]
+ operation_log_info['login_info'] = f'{oper_name} / {oper_ip} / {oper_location}'
+ operation_log_info['status'] = '正常' if operation_log_info.get('status') == 0 else '失败'
+ operation_log_info['cost_time'] = f"{operation_log_info.get('cost_time')}毫秒"
+ return dict(
+ modal_visible=True,
+ modal_title='操作日志详情',
+ form_value=[operation_log_info.get(k) for k in form_value_list],
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 12 + [{'timestamp': time.time()}]
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 13
+ raise PreventUpdate
@app.callback(
@@ -200,17 +224,18 @@ def add_edit_operation_log_modal(button_click, clicked_content, recently_button_
prevent_initial_call=True
)
def change_operation_log_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -222,6 +247,9 @@ def change_operation_log_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def operation_log_delete_modal(operation_click, selected_row_keys):
+ """
+ 显示删除或清空操作日志二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.index in ['delete', 'clear']:
if trigger_id.index == 'delete':
@@ -240,7 +268,7 @@ def operation_log_delete_modal(operation_click, selected_row_keys):
{'oper_type': 'clear', 'oper_ids': ''}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -252,6 +280,9 @@ def operation_log_delete_modal(operation_click, selected_row_keys):
prevent_initial_call=True
)
def operation_log_delete_confirm(delete_confirm, oper_ids_data):
+ """
+ 删除或清空操作日志弹窗确认回调,实现删除或清空操作
+ """
if delete_confirm:
oper_type = oper_ids_data.get('oper_type')
@@ -286,7 +317,7 @@ def operation_log_delete_confirm(delete_confirm, oper_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -298,6 +329,9 @@ def operation_log_delete_confirm(delete_confirm, oper_ids_data):
prevent_initial_call=True
)
def export_operation_log_list(export_click):
+ """
+ 导出操作日志信息回调
+ """
if export_click:
export_operation_log_res = export_operation_log_list_api({})
if export_operation_log_res.status_code == 200:
@@ -317,7 +351,7 @@ def export_operation_log_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -326,9 +360,12 @@ def export_operation_log_list(export_click):
prevent_initial_call=True
)
def reset_operation_log_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/config_c.py b/dash-fastapi-frontend/callbacks/system_c/config_c.py
index b0d2ca4f675f719db4541cf9cc4a5be9ca054e79..47bf411f393be4afa1ad31e4d68422f8e95e725d 100644
--- a/dash-fastapi-frontend/callbacks/system_c/config_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/config_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -10,23 +11,32 @@ from api.config import get_config_list_api, get_config_detail_api, add_config_ap
@app.callback(
- [Output('config-list-table', 'data', allow_duplicate=True),
- Output('config-list-table', 'pagination', allow_duplicate=True),
- Output('config-list-table', 'key'),
- Output('config-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('config-search', 'nClicks'),
- Input('config-refresh', 'nClicks'),
- Input('config-list-table', 'pagination'),
- Input('config-operations-store', 'data')],
- [State('config-config_name-input', 'value'),
- State('config-config_key-input', 'value'),
- State('config-config_type-select', 'value'),
- State('config-create_time-range', 'value'),
- State('config-button-perms-container', 'data')],
+ output=dict(
+ config_table_data=Output('config-list-table', 'data', allow_duplicate=True),
+ config_table_pagination=Output('config-list-table', 'pagination', allow_duplicate=True),
+ config_table_key=Output('config-list-table', 'key'),
+ config_table_selectedrowkeys=Output('config-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('config-search', 'nClicks'),
+ refresh_click=Input('config-refresh', 'nClicks'),
+ pagination=Input('config-list-table', 'pagination'),
+ operations=Input('config-operations-store', 'data')
+ ),
+ state=dict(
+ config_name=State('config-config_name-input', 'value'),
+ config_key=State('config-config_key-input', 'value'),
+ config_type=State('config-config_type-select', 'value'),
+ create_time_range=State('config-create_time-range', 'value'),
+ button_perms=State('config-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_config_table_data(search_click, refresh_click, pagination, operations, config_name, config_key, config_type, create_time_range, button_perms):
+ """
+ 获取参数设置表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
create_time_start = None
create_time_end = None
if create_time_range:
@@ -84,13 +94,26 @@ def get_config_table_data(search_click, refresh_click, pagination, operations, c
} if 'system:config:remove' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ config_table_data=table_data,
+ config_table_pagination=table_pagination,
+ config_table_key=str(uuid.uuid4()),
+ config_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ config_table_data=dash.no_update,
+ config_table_pagination=dash.no_update,
+ config_table_key=dash.no_update,
+ config_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置参数设置搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -110,6 +133,7 @@ app.clientside_callback(
)
+# 隐藏/显示参数设置搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -136,6 +160,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_config_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -146,7 +173,7 @@ def change_config_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -155,55 +182,66 @@ def change_config_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_config_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
- [Output('config-modal', 'visible', allow_duplicate=True),
- Output('config-modal', 'title'),
- Output('config-config_name', 'value'),
- Output('config-config_key', 'value'),
- Output('config-config_value', 'value'),
- Output('config-config_type', 'value'),
- Output('config-remark', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('config-edit-id-store', 'data'),
- Output('config-operations-store-bk', 'data')],
- [Input({'type': 'config-operation-button', 'index': ALL}, 'nClicks'),
- Input('config-list-table', 'nClicksButton')],
- [State('config-list-table', 'selectedRowKeys'),
- State('config-list-table', 'clickedContent'),
- State('config-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal_visible=Output('config-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('config-modal', 'title'),
+ form_value=Output({'type': 'config-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'config-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'config-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('config-edit-id-store', 'data'),
+ modal_type=Output('config-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'config-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('config-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ selected_row_keys=State('config-list-table', 'selectedRowKeys'),
+ clicked_content=State('config-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('config-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_config_modal(operation_click, button_click, selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示新增或编辑参数设置弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'config-operation-button'} \
or trigger_id == {'index': 'edit', 'type': 'config-operation-button'} \
or (trigger_id == 'config-list-table' and clicked_content == '修改'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
if trigger_id == {'index': 'add', 'type': 'config-operation-button'}:
- return [
- True,
- '新增参数',
- None,
- None,
- None,
- 'Y',
- None,
- dash.no_update,
- None,
- {'type': 'add'}
- ]
+ config_info = dict(config_name=None, config_key=None, config_value=None, config_type='Y', remark=None)
+ return dict(
+ modal_visible=True,
+ modal_title='新增参数',
+ form_value=[config_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger=dash.no_update,
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id == {'index': 'edit', 'type': 'config-operation-button'} or (trigger_id == 'config-list-table' and clicked_content == '修改'):
if trigger_id == {'index': 'edit', 'type': 'config-operation-button'}:
config_id = int(','.join(selected_row_keys))
@@ -212,114 +250,112 @@ def add_edit_config_modal(operation_click, button_click, selected_row_keys, clic
config_info_res = get_config_detail_api(config_id=config_id)
if config_info_res['code'] == 200:
config_info = config_info_res['data']
- return [
- True,
- '编辑参数',
- config_info.get('config_name'),
- config_info.get('config_key'),
- config_info.get('config_value'),
- config_info.get('config_type'),
- config_info.get('remark'),
- {'timestamp': time.time()},
- config_info if config_info else None,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 7 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑参数',
+ form_value=[config_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=config_info if config_info else None,
+ modal_type={'type': 'edit'}
+ )
+
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
- return [dash.no_update] * 8 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('config-config_name-form-item', 'validateStatus'),
- Output('config-config_key-form-item', 'validateStatus'),
- Output('config-config_value-form-item', 'validateStatus'),
- Output('config-config_name-form-item', 'help'),
- Output('config-config_key-form-item', 'help'),
- Output('config-config_value-form-item', 'help'),
- Output('config-modal', 'visible'),
- Output('config-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('config-modal', 'okCounts'),
- [State('config-operations-store-bk', 'data'),
- State('config-edit-id-store', 'data'),
- State('config-config_name', 'value'),
- State('config-config_key', 'value'),
- State('config-config_value', 'value'),
- State('config-config_type', 'value'),
- State('config-remark', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'config-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'config-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('config-modal', 'visible'),
+ operations=Output('config-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('config-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('config-operations-store-bk', 'data'),
+ edit_row_info=State('config-edit-id-store', 'data'),
+ form_value=State({'type': 'config-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'config-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def dict_type_confirm(confirm_trigger, operation_type, cur_config_info, config_name, config_key, config_value, config_type, remark):
+def dict_type_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label):
+ """
+ 新增或编辑参数设置弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([config_name, config_key, config_value]):
- params_add = dict(config_name=config_name, config_key=config_key, config_value=config_value,
- config_type=config_type, remark=remark)
- params_edit = dict(config_id=cur_config_info.get('config_id') if cur_config_info else None,
- config_name=config_name, config_key=config_key, config_value=config_value,
- config_type=config_type, remark=remark)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params_add = form_value_state
+ params_edit = params_add.copy()
+ params_edit['config_id'] = edit_row_info.get('config_id') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_config_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_config_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [
- None if config_name else 'error',
- None if config_key else 'error',
- None if config_value else 'error',
- None if config_name else '请输入参数名称!',
- None if config_key else '请输入参数键名!',
- None if config_value else '请输入参数键值!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 10
+ raise PreventUpdate
@app.callback(
@@ -335,6 +371,9 @@ def dict_type_confirm(confirm_trigger, operation_type, cur_config_info, config_n
)
def config_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除参数设置二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'config-operation-button'} or (
trigger_id == 'config-list-table' and clicked_content == '删除'):
@@ -353,7 +392,7 @@ def config_delete_modal(operation_click, button_click,
{'config_ids': config_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -365,6 +404,9 @@ def config_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def config_delete_confirm(delete_confirm, config_ids_data):
+ """
+ 删除参数设置弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = config_ids_data
@@ -382,7 +424,7 @@ def config_delete_confirm(delete_confirm, config_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -394,6 +436,9 @@ def config_delete_confirm(delete_confirm, config_ids_data):
prevent_initial_call=True
)
def export_config_list(export_click):
+ """
+ 导出参数设置信息回调
+ """
if export_click:
export_config_res = export_config_list_api({})
if export_config_res.status_code == 200:
@@ -413,7 +458,7 @@ def export_config_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -422,12 +467,15 @@ def export_config_list(export_click):
prevent_initial_call=True
)
def reset_config_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -437,6 +485,9 @@ def reset_config_export_status(data):
prevent_initial_call=True
)
def refresh_config_cache(refresh_click):
+ """
+ 刷新缓存回调
+ """
if refresh_click:
refresh_info_res = refresh_config_api({})
if refresh_info_res.get('code') == 200:
@@ -450,4 +501,4 @@ def refresh_config_cache(refresh_click):
fuc.FefferyFancyMessage('刷新失败', type='error')
]
- return [dash.no_update] * 2
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/dept_c.py b/dash-fastapi-frontend/callbacks/system_c/dept_c.py
index 8ce33e5491dc0e8e912071fa18ba4458c7218a42..660cc533e75a8b263be416062c4a72d73209a906 100644
--- a/dash-fastapi-frontend/callbacks/system_c/dept_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/dept_c.py
@@ -2,6 +2,7 @@ import dash
import time
import uuid
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -11,23 +12,32 @@ from api.dept import get_dept_tree_api, get_dept_list_api, add_dept_api, edit_de
@app.callback(
- [Output('dept-list-table', 'data', allow_duplicate=True),
- Output('dept-list-table', 'key'),
- Output('dept-list-table', 'defaultExpandedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('dept-fold', 'nClicks')],
- [Input('dept-search', 'nClicks'),
- Input('dept-refresh', 'nClicks'),
- Input('dept-operations-store', 'data'),
- Input('dept-fold', 'nClicks')],
- [State('dept-dept_name-input', 'value'),
- State('dept-status-select', 'value'),
- State('dept-list-table', 'defaultExpandedRowKeys'),
- State('dept-button-perms-container', 'data')],
+ output=dict(
+ dept_table_data=Output('dept-list-table', 'data', allow_duplicate=True),
+ dept_table_key=Output('dept-list-table', 'key'),
+ dept_table_defaultexpandedrowkeys=Output('dept-list-table', 'defaultExpandedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ fold_click=Output('dept-fold', 'nClicks')
+ ),
+ inputs=dict(
+ search_click=Input('dept-search', 'nClicks'),
+ refresh_click=Input('dept-refresh', 'nClicks'),
+ operations=Input('dept-operations-store', 'data'),
+ fold_click=Input('dept-fold', 'nClicks')
+ ),
+ state=dict(
+ dept_name=State('dept-dept_name-input', 'value'),
+ status_select=State('dept-status-select', 'value'),
+ in_default_expanded_row_keys=State('dept-list-table', 'defaultExpandedRowKeys'),
+ button_perms=State('dept-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
-def get_dept_table_data(search_click, refresh_click, operations, fold_click, dept_name, status_select, in_default_expanded_row_keys, button_perms):
-
+def get_dept_table_data(search_click, refresh_click, operations, fold_click, dept_name, status_select,
+ in_default_expanded_row_keys, button_perms):
+ """
+ 获取部门表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
dept_name=dept_name,
status=status_select
@@ -92,15 +102,40 @@ def get_dept_table_data(search_click, refresh_click, operations, fold_click, dep
if fold_click:
if in_default_expanded_row_keys:
- return [table_data_new, str(uuid.uuid4()), [], {'timestamp': time.time()}, None]
+ return dict(
+ dept_table_data=table_data_new,
+ dept_table_key=str(uuid.uuid4()),
+ dept_table_defaultexpandedrowkeys=[],
+ api_check_token_trigger={'timestamp': time.time()},
+ fold_click=None
+ )
- return [table_data_new, str(uuid.uuid4()), default_expanded_row_keys, {'timestamp': time.time()}, None]
+ return dict(
+ dept_table_data=table_data_new,
+ dept_table_key=str(uuid.uuid4()),
+ dept_table_defaultexpandedrowkeys=default_expanded_row_keys,
+ api_check_token_trigger={'timestamp': time.time()},
+ fold_click=None
+ )
- return [dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}, None]
+ return dict(
+ dept_table_data=dash.no_update,
+ dept_table_key=dash.no_update,
+ dept_table_defaultexpandedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ fold_click=None
+ )
- return [dash.no_update] * 4 + [None]
+ return dict(
+ dept_table_data=dash.no_update,
+ dept_table_key=dash.no_update,
+ dept_table_defaultexpandedrowkeys=dash.no_update,
+ api_check_token_trigger=dash.no_update,
+ fold_click=None
+ )
+# 重置部门搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -117,7 +152,7 @@ app.clientside_callback(
prevent_initial_call=True
)
-
+# 隐藏/显示部门搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -139,29 +174,39 @@ app.clientside_callback(
@app.callback(
- [Output('dept-modal', 'visible', allow_duplicate=True),
- Output('dept-modal', 'title'),
- Output('dept-parent_id-div', 'hidden'),
- Output('dept-parent_id', 'treeData'),
- Output('dept-parent_id', 'value'),
- Output('dept-dept_name', 'value'),
- Output('dept-order_num', 'value'),
- Output('dept-leader', 'value'),
- Output('dept-phone', 'value'),
- Output('dept-email', 'value'),
- Output('dept-status', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('dept-edit-id-store', 'data'),
- Output('dept-operations-store-bk', 'data')],
- [Input({'type': 'dept-operation-button', 'index': ALL}, 'nClicks'),
- Input('dept-list-table', 'nClicksButton')],
- [State('dept-list-table', 'clickedContent'),
- State('dept-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal_visible=Output('dept-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('dept-modal', 'title'),
+ parent_id_div_ishidden=Output('dept-parent_id-div', 'hidden'),
+ parent_id_tree=Output({'type': 'dept-form-value', 'index': 'parent_id'}, 'treeData'),
+ form_value=Output({'type': 'dept-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'dept-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'dept-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('dept-edit-id-store', 'data'),
+ modal_type=Output('dept-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'dept-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('dept-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ clicked_content=State('dept-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('dept-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_dept_modal(operation_click, button_click, clicked_content, recently_button_clicked_row):
+ """
+ 显示新增或编辑部门弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
- if trigger_id == {'index': 'add', 'type': 'dept-operation-button'} or (trigger_id == 'dept-list-table' and clicked_content != '删除'):
+ if trigger_id == {'index': 'add', 'type': 'dept-operation-button'} or (
+ trigger_id == 'dept-list-table' and clicked_content != '删除'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[4]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[5]]
dept_params = dict(dept_name='')
if trigger_id == 'dept-list-table' and clicked_content == '修改':
dept_params['dept_id'] = int(recently_button_clicked_row['key'])
@@ -171,176 +216,143 @@ def add_edit_dept_modal(operation_click, button_click, clicked_content, recently
if tree_info['code'] == 200:
tree_data = tree_info['data']
- if trigger_id == {'index': 'add', 'type': 'dept-operation-button'}:
- return [
- True,
- '新增部门',
- False,
- tree_data,
- None,
- None,
- None,
- None,
- None,
- None,
- '0',
- {'timestamp': time.time()},
- None,
- {'type': 'add'}
- ]
- elif trigger_id == 'dept-list-table' and clicked_content == '新增':
- return [
- True,
- '新增部门',
- False,
- tree_data,
- str(recently_button_clicked_row['key']),
- None,
- None,
- None,
- None,
- None,
- '0',
- {'timestamp': time.time()},
- None,
- {'type': 'add'}
- ]
+ if trigger_id == {'index': 'add', 'type': 'dept-operation-button'} or (trigger_id == 'dept-list-table' and clicked_content == '新增'):
+ dept_info = dict(
+ parent_id=None if trigger_id == {'index': 'add', 'type': 'dept-operation-button'} else str(recently_button_clicked_row['key']),
+ dept_name=None,
+ order_num=None,
+ leader=None,
+ phone=None,
+ email=None,
+ status='0',
+ )
+ return dict(
+ modal_visible=True,
+ modal_title='新增部门',
+ parent_id_div_ishidden=False,
+ parent_id_tree=tree_data,
+ form_value=[dept_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id == 'dept-list-table' and clicked_content == '修改':
dept_id = int(recently_button_clicked_row['key'])
dept_info_res = get_dept_detail_api(dept_id=dept_id)
if dept_info_res['code'] == 200:
dept_info = dept_info_res['data']
- if dept_info.get('parent_id') == 0:
- return [
- True,
- '编辑部门',
- True,
- tree_data,
- str(dept_info.get('parent_id')),
- dept_info.get('dept_name'),
- dept_info.get('order_num'),
- dept_info.get('leader'),
- dept_info.get('phone'),
- dept_info.get('email'),
- dept_info.get('status'),
- {'timestamp': time.time()},
- dept_info,
- {'type': 'edit'}
- ]
- else:
- return [
- True,
- '编辑部门',
- False,
- tree_data,
- str(dept_info.get('parent_id')),
- dept_info.get('dept_name'),
- dept_info.get('order_num'),
- dept_info.get('leader'),
- dept_info.get('phone'),
- dept_info.get('email'),
- dept_info.get('status'),
- {'timestamp': time.time()},
- dept_info,
- {'type': 'edit'}
- ]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑部门',
+ parent_id_div_ishidden=dept_info.get('parent_id') == 0,
+ parent_id_tree=tree_data,
+ form_value=[dept_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=dept_info,
+ modal_type={'type': 'edit'}
+ )
- return [dash.no_update] * 11 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ parent_id_div_ishidden=dash.no_update,
+ parent_id_tree=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
- return [dash.no_update] * 12 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('dept-parent_id-form-item', 'validateStatus'),
- Output('dept-dept_name-form-item', 'validateStatus'),
- Output('dept-order_num-form-item', 'validateStatus'),
- Output('dept-parent_id-form-item', 'help'),
- Output('dept-dept_name-form-item', 'help'),
- Output('dept-order_num-form-item', 'help'),
- Output('dept-modal', 'visible'),
- Output('dept-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('dept-modal', 'okCounts'),
- [State('dept-operations-store-bk', 'data'),
- State('dept-edit-id-store', 'data'),
- State('dept-parent_id', 'value'),
- State('dept-dept_name', 'value'),
- State('dept-order_num', 'value'),
- State('dept-leader', 'value'),
- State('dept-phone', 'value'),
- State('dept-email', 'value'),
- State('dept-status', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'dept-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'dept-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('dept-modal', 'visible'),
+ operations=Output('dept-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('dept-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('dept-operations-store-bk', 'data'),
+ edit_row_info=State('dept-edit-id-store', 'data'),
+ form_value=State({'type': 'dept-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'dept-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def dept_confirm(confirm_trigger, operation_type, cur_dept_info, parent_id, dept_name, order_num, leader, phone, email, status):
+def dept_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label):
+ """
+ 新增或编辑部门弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([parent_id, dept_name, order_num]):
- params_add = dict(parent_id=parent_id, dept_name=dept_name, order_num=order_num, leader=leader, phone=phone,
- email=email, status=status)
- params_edit = dict(dept_id=cur_dept_info.get('dept_id') if cur_dept_info else None, parent_id=parent_id, dept_name=dept_name,
- order_num=order_num, leader=leader, phone=phone, email=email, status=status)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params_add = form_value_state
+ params_edit = params_add.copy()
+ params_edit['dept_id'] = edit_row_info.get('dept_id') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_dept_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_dept_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
-
- return [
- None if parent_id else 'error',
- None if dept_name else 'error',
- None if order_num else 'error',
- None if parent_id else '请选择上级部门!',
- None if dept_name else '请输入部门名称!',
- None if order_num else '请输入显示排序!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 10
+ raise PreventUpdate
@app.callback(
@@ -353,6 +365,9 @@ def dept_confirm(confirm_trigger, operation_type, cur_dept_info, parent_id, dept
prevent_initial_call=True
)
def dept_delete_modal(button_click, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除部门二次确认弹窗回调
+ """
if button_click:
if clicked_content == '删除':
@@ -366,7 +381,7 @@ def dept_delete_modal(button_click, clicked_content, recently_button_clicked_row
{'dept_ids': dept_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -378,6 +393,9 @@ def dept_delete_modal(button_click, clicked_content, recently_button_clicked_row
prevent_initial_call=True
)
def dept_delete_confirm(delete_confirm, dept_ids_data):
+ """
+ 删除部门弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = dept_ids_data
@@ -395,4 +413,4 @@ def dept_delete_confirm(delete_confirm, dept_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_c.py b/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_c.py
index 2cb608f4f18f491a8861f07c4a713573431c7712..a2b87cc66a58361a2a2e5fcf4b494f38e989b60a 100644
--- a/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -10,23 +11,32 @@ from api.dict import get_dict_type_list_api, get_all_dict_type_api, get_dict_typ
@app.callback(
- [Output('dict_type-list-table', 'data', allow_duplicate=True),
- Output('dict_type-list-table', 'pagination', allow_duplicate=True),
- Output('dict_type-list-table', 'key'),
- Output('dict_type-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('dict_type-search', 'nClicks'),
- Input('dict_type-refresh', 'nClicks'),
- Input('dict_type-list-table', 'pagination'),
- Input('dict_type-operations-store', 'data')],
- [State('dict_type-dict_name-input', 'value'),
- State('dict_type-dict_type-input', 'value'),
- State('dict_type-status-select', 'value'),
- State('dict_type-create_time-range', 'value'),
- State('dict_type-button-perms-container', 'data')],
+ output=dict(
+ dict_type_table_data=Output('dict_type-list-table', 'data', allow_duplicate=True),
+ dict_type_table_pagination=Output('dict_type-list-table', 'pagination', allow_duplicate=True),
+ dict_type_table_key=Output('dict_type-list-table', 'key'),
+ dict_type_table_selectedrowkeys=Output('dict_type-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('dict_type-search', 'nClicks'),
+ refresh_click=Input('dict_type-refresh', 'nClicks'),
+ pagination=Input('dict_type-list-table', 'pagination'),
+ operations=Input('dict_type-operations-store', 'data')
+ ),
+ state=dict(
+ dict_name=State('dict_type-dict_name-input', 'value'),
+ dict_type=State('dict_type-dict_type-input', 'value'),
+ status_select=State('dict_type-status-select', 'value'),
+ create_time_range=State('dict_type-create_time-range', 'value'),
+ button_perms=State('dict_type-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_dict_type_table_data(search_click, refresh_click, pagination, operations, dict_name, dict_type, status_select, create_time_range, button_perms):
+ """
+ 获取字典类型表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
create_time_start = None
create_time_end = None
if create_time_range:
@@ -88,13 +98,26 @@ def get_dict_type_table_data(search_click, refresh_click, pagination, operations
} if 'system:dict:remove' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ dict_type_table_data=table_data,
+ dict_type_table_pagination=table_pagination,
+ dict_type_table_key=str(uuid.uuid4()),
+ dict_type_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ dict_type_table_data=dash.no_update,
+ dict_type_table_pagination=dash.no_update,
+ dict_type_table_key=dash.no_update,
+ dict_type_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置字典类型搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -114,6 +137,7 @@ app.clientside_callback(
)
+# 隐藏/显示字典类型搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -140,6 +164,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_dict_type_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -150,7 +177,7 @@ def change_dict_type_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -159,53 +186,66 @@ def change_dict_type_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_dict_type_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
- [Output('dict_type-modal', 'visible', allow_duplicate=True),
- Output('dict_type-modal', 'title'),
- Output('dict_type-dict_name', 'value'),
- Output('dict_type-dict_type', 'value'),
- Output('dict_type-status', 'value'),
- Output('dict_type-remark', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('dict_type-edit-id-store', 'data'),
- Output('dict_type-operations-store-bk', 'data')],
- [Input({'type': 'dict_type-operation-button', 'index': ALL}, 'nClicks'),
- Input('dict_type-list-table', 'nClicksButton')],
- [State('dict_type-list-table', 'selectedRowKeys'),
- State('dict_type-list-table', 'clickedContent'),
- State('dict_type-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal_visible=Output('dict_type-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('dict_type-modal', 'title'),
+ form_value=Output({'type': 'dict_type-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'dict_type-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'dict_type-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('dict_type-edit-id-store', 'data'),
+ modal_type=Output('dict_type-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'dict_type-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('dict_type-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ selected_row_keys=State('dict_type-list-table', 'selectedRowKeys'),
+ clicked_content=State('dict_type-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('dict_type-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_dict_type_modal(operation_click, button_click, selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示新增或编辑字典类型弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'dict_type-operation-button'} \
or trigger_id == {'index': 'edit', 'type': 'dict_type-operation-button'} \
or (trigger_id == 'dict_type-list-table' and clicked_content == '修改'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
if trigger_id == {'index': 'add', 'type': 'dict_type-operation-button'}:
- return [
- True,
- '新增字典类型',
- None,
- None,
- '0',
- None,
- dash.no_update,
- None,
- {'type': 'add'}
- ]
+ dict_type_info = dict(dict_name=None, dict_type=None, status='0', remark=None,)
+ return dict(
+ modal_visible=True,
+ modal_title='新增字典类型',
+ form_value=[dict_type_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger=dash.no_update,
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id == {'index': 'edit', 'type': 'dict_type-operation-button'} or (trigger_id == 'dict_type-list-table' and clicked_content == '修改'):
if trigger_id == {'index': 'edit', 'type': 'dict_type-operation-button'}:
dict_id = int(','.join(selected_row_keys))
@@ -214,100 +254,112 @@ def add_edit_dict_type_modal(operation_click, button_click, selected_row_keys, c
dict_type_info_res = get_dict_type_detail_api(dict_id=dict_id)
if dict_type_info_res['code'] == 200:
dict_type_info = dict_type_info_res['data']
- return [
- True,
- '编辑字典类型',
- dict_type_info.get('dict_name'),
- dict_type_info.get('dict_type'),
- dict_type_info.get('status'),
- dict_type_info.get('remark'),
- {'timestamp': time.time()},
- dict_type_info if dict_type_info else None,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 6 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑字典类型',
+ form_value=[dict_type_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=dict_type_info if dict_type_info else None,
+ modal_type={'type': 'edit'}
+ )
+
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
- return [dash.no_update] * 7 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('dict_type-dict_name-form-item', 'validateStatus'),
- Output('dict_type-dict_type-form-item', 'validateStatus'),
- Output('dict_type-dict_name-form-item', 'help'),
- Output('dict_type-dict_type-form-item', 'help'),
- Output('dict_type-modal', 'visible'),
- Output('dict_type-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('dict_type-modal', 'okCounts'),
- [State('dict_type-operations-store-bk', 'data'),
- State('dict_type-edit-id-store', 'data'),
- State('dict_type-dict_name', 'value'),
- State('dict_type-dict_type', 'value'),
- State('dict_type-status', 'value'),
- State('dict_type-remark', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'dict_type-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'dict_type-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('dict_type-modal', 'visible'),
+ operations=Output('dict_type-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('dict_type-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('dict_type-operations-store-bk', 'data'),
+ edit_row_info=State('dict_type-edit-id-store', 'data'),
+ form_value=State({'type': 'dict_type-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'dict_type-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def dict_type_confirm(confirm_trigger, operation_type, cur_post_info, dict_name, dict_type, status, remark):
+def dict_type_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label):
+ """
+ 新增或编字典类型弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([dict_name, dict_type]):
- params_add = dict(dict_name=dict_name, dict_type=dict_type, status=status, remark=remark)
- params_edit = dict(dict_id=cur_post_info.get('dict_id') if cur_post_info else None, dict_name=dict_name,
- dict_type=dict_type, status=status, remark=remark)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params_add = form_value_state
+ params_edit = params_add.copy()
+ params_edit['dict_id'] = edit_row_info.get('dict_id') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_dict_type_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_dict_type_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [
- None if dict_name else 'error',
- None if dict_type else 'error',
- None if dict_name else '请输入字典名称!',
- None if dict_type else '请输入字典类型!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 8
+ raise PreventUpdate
@app.callback(
@@ -323,6 +375,9 @@ def dict_type_confirm(confirm_trigger, operation_type, cur_post_info, dict_name,
)
def dict_type_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除字典类型二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'dict_type-operation-button'} or (
trigger_id == 'dict_type-list-table' and clicked_content == '删除'):
@@ -341,7 +396,7 @@ def dict_type_delete_modal(operation_click, button_click,
{'dict_ids': dict_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -353,6 +408,9 @@ def dict_type_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def dict_type_delete_confirm(delete_confirm, dict_ids_data):
+ """
+ 删除字典类型弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = dict_ids_data
@@ -370,23 +428,32 @@ def dict_type_delete_confirm(delete_confirm, dict_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
- [Output('dict_type_to_dict_data-modal', 'visible'),
- Output('dict_type_to_dict_data-modal', 'title'),
- Output('dict_data-dict_type-select', 'options'),
- Output('dict_data-dict_type-select', 'value', allow_duplicate=True),
- Output('dict_data-search', 'nClicks'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- Input('dict_type-list-table', 'nClicksButton'),
- [State('dict_type-list-table', 'clickedContent'),
- State('dict_type-list-table', 'recentlyButtonClickedRow'),
- State('dict_data-search', 'nClicks')],
+ output=dict(
+ dict_data_modal_visible=Output('dict_type_to_dict_data-modal', 'visible'),
+ dict_data_modal_title=Output('dict_type_to_dict_data-modal', 'title'),
+ dict_data_select_options=Output('dict_data-dict_type-select', 'options'),
+ dict_data_select_value=Output('dict_data-dict_type-select', 'value', allow_duplicate=True),
+ dict_data_search_nclick=Output('dict_data-search', 'nClicks'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ button_click=Input('dict_type-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ clicked_content=State('dict_type-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('dict_type-list-table', 'recentlyButtonClickedRow'),
+ dict_data_search_nclick=State('dict_data-search', 'nClicks')
+ ),
prevent_initial_call=True
)
def dict_type_to_dict_data_modal(button_click, clicked_content, recently_button_clicked_row, dict_data_search_nclick):
+ """
+ 显示字典类型对应数据表格弹窗回调
+ """
if button_click and clicked_content == recently_button_clicked_row.get('dict_type').get('content'):
all_dict_type_info = get_all_dict_type_api({})
@@ -394,25 +461,25 @@ def dict_type_to_dict_data_modal(button_click, clicked_content, recently_button_
all_dict_type = all_dict_type_info.get('data')
dict_data_options = [dict(label=item.get('dict_name'), value=item.get('dict_type')) for item in all_dict_type]
- return [
- True,
- '字典数据',
- dict_data_options,
- recently_button_clicked_row.get('dict_type').get('content'),
- dict_data_search_nclick + 1 if dict_data_search_nclick else 1,
- {'timestamp': time.time()},
- ]
+ return dict(
+ dict_data_modal_visible=True,
+ dict_data_modal_title='字典数据',
+ dict_data_select_options=dict_data_options,
+ dict_data_select_value=recently_button_clicked_row.get('dict_type').get('content'),
+ dict_data_search_nclick=dict_data_search_nclick + 1 if dict_data_search_nclick else 1,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [
- True,
- '字典数据',
- [],
- recently_button_clicked_row.get('dict_type').get('content'),
- dict_data_search_nclick + 1 if dict_data_search_nclick else 1,
- {'timestamp': time.time()},
- ]
+ return dict(
+ dict_data_modal_visible=True,
+ dict_data_modal_title='字典数据',
+ dict_data_select_options=[],
+ dict_data_select_value=recently_button_clicked_row.get('dict_type').get('content'),
+ dict_data_search_nclick=dict_data_search_nclick + 1 if dict_data_search_nclick else 1,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 6
+ raise PreventUpdate
@app.callback(
@@ -424,6 +491,9 @@ def dict_type_to_dict_data_modal(button_click, clicked_content, recently_button_
prevent_initial_call=True
)
def export_dict_type_list(export_click):
+ """
+ 导出字典类型信息回调
+ """
if export_click:
export_dict_type_res = export_dict_type_list_api({})
if export_dict_type_res.status_code == 200:
@@ -443,7 +513,7 @@ def export_dict_type_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -452,12 +522,15 @@ def export_dict_type_list(export_click):
prevent_initial_call=True
)
def reset_dict_type_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -467,6 +540,9 @@ def reset_dict_type_export_status(data):
prevent_initial_call=True
)
def refresh_dict_cache(refresh_click):
+ """
+ 刷新缓存回调
+ """
if refresh_click:
refresh_info_res = refresh_dict_api({})
if refresh_info_res.get('code') == 200:
@@ -480,4 +556,4 @@ def refresh_dict_cache(refresh_click):
fuc.FefferyFancyMessage('刷新失败', type='error')
]
- return [dash.no_update] * 2
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_data_c.py b/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_data_c.py
index c01bcb637d91cd60e70699a1ffc3749ce87f338e..f5c98bc29a8717b594822dd9cdd92561408df2be 100644
--- a/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_data_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/dict_c/dict_data_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -10,22 +11,31 @@ from api.dict import get_dict_data_list_api, get_dict_data_detail_api, add_dict_
@app.callback(
- [Output('dict_data-list-table', 'data', allow_duplicate=True),
- Output('dict_data-list-table', 'pagination', allow_duplicate=True),
- Output('dict_data-list-table', 'key'),
- Output('dict_data-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('dict_data-search', 'nClicks'),
- Input('dict_data-refresh', 'nClicks'),
- Input('dict_data-list-table', 'pagination'),
- Input('dict_data-operations-store', 'data')],
- [State('dict_data-dict_type-select', 'value'),
- State('dict_data-dict_label-input', 'value'),
- State('dict_data-status-select', 'value'),
- State('dict_data-button-perms-container', 'data')],
+ output=dict(
+ dict_data_table_data=Output('dict_data-list-table', 'data', allow_duplicate=True),
+ dict_data_table_pagination=Output('dict_data-list-table', 'pagination', allow_duplicate=True),
+ dict_data_table_key=Output('dict_data-list-table', 'key'),
+ dict_data_table_selectedrowkeys=Output('dict_data-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('dict_data-search', 'nClicks'),
+ refresh_click=Input('dict_data-refresh', 'nClicks'),
+ pagination=Input('dict_data-list-table', 'pagination'),
+ operations=Input('dict_data-operations-store', 'data')
+ ),
+ state=dict(
+ dict_type=State('dict_data-dict_type-select', 'value'),
+ dict_label=State('dict_data-dict_label-input', 'value'),
+ status_select=State('dict_data-status-select', 'value'),
+ button_perms=State('dict_data-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_dict_data_table_data(search_click, refresh_click, pagination, operations, dict_type, dict_label, status_select, button_perms):
+ """
+ 获取字典数据表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
dict_type=dict_type,
@@ -74,13 +84,26 @@ def get_dict_data_table_data(search_click, refresh_click, pagination, operations
} if 'system:dict:remove' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ dict_data_table_data=table_data,
+ dict_data_table_pagination=table_pagination,
+ dict_data_table_key=str(uuid.uuid4()),
+ dict_data_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ dict_data_table_data=dash.no_update,
+ dict_data_table_pagination=dash.no_update,
+ dict_data_table_key=dash.no_update,
+ dict_data_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置字典数据搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -98,6 +121,7 @@ app.clientside_callback(
)
+# 隐藏/显示字典数据搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -124,6 +148,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_dict_data_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -134,7 +161,7 @@ def change_dict_data_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -143,63 +170,77 @@ def change_dict_data_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_dict_data_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
- [Output('dict_data-modal', 'visible', allow_duplicate=True),
- Output('dict_data-modal', 'title'),
- Output('dict_data-dict_type', 'value'),
- Output('dict_data-dict_label', 'value'),
- Output('dict_data-dict_value', 'value'),
- Output('dict_data-css_class', 'value'),
- Output('dict_data-dict_sort', 'value'),
- Output('dict_data-list_class', 'value'),
- Output('dict_data-status', 'value'),
- Output('dict_data-remark', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('dict_data-edit-id-store', 'data'),
- Output('dict_data-operations-store-bk', 'data')],
- [Input({'type': 'dict_data-operation-button', 'index': ALL}, 'nClicks'),
- Input('dict_data-list-table', 'nClicksButton')],
- [State('dict_data-list-table', 'selectedRowKeys'),
- State('dict_data-list-table', 'clickedContent'),
- State('dict_data-list-table', 'recentlyButtonClickedRow'),
- State('dict_data-dict_type-select', 'value')],
+ output=dict(
+ modal_visible=Output('dict_data-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('dict_data-modal', 'title'),
+ form_value=Output({'type': 'dict_data-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'dict_data-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'dict_data-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('dict_data-edit-id-store', 'data'),
+ modal_type=Output('dict_data-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'dict_data-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('dict_data-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ selected_row_keys=State('dict_data-list-table', 'selectedRowKeys'),
+ clicked_content=State('dict_data-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('dict_data-list-table', 'recentlyButtonClickedRow'),
+ dict_type_select=State('dict_data-dict_type-select', 'value')
+ ),
prevent_initial_call=True
)
def add_edit_dict_data_modal(operation_click, button_click, selected_row_keys, clicked_content,
recently_button_clicked_row, dict_type_select):
+ """
+ 显示新增或编辑字典数据弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'dict_data-operation-button'} \
or trigger_id == {'index': 'edit', 'type': 'dict_data-operation-button'} \
or (trigger_id == 'dict_data-list-table' and clicked_content == '修改'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
if trigger_id == {'index': 'add', 'type': 'dict_data-operation-button'}:
- return [
- True,
- '新增字典数据',
- dict_type_select,
- None,
- None,
- None,
- 0,
- 'default',
- '0',
- None,
- dash.no_update,
- None,
- {'type': 'add'}
- ]
+ dict_data_info = dict(
+ dict_type=dict_type_select,
+ dict_label=None,
+ dict_value=None,
+ css_class=None,
+ dict_sort=0,
+ list_class='default',
+ status='0',
+ remark=None
+ )
+ return dict(
+ modal_visible=True,
+ modal_title='新增字典数据',
+ form_value=[dict_data_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger=dash.no_update,
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id == {'index': 'edit', 'type': 'dict_data-operation-button'} or (trigger_id == 'dict_data-list-table' and clicked_content == '修改'):
if trigger_id == {'index': 'edit', 'type': 'dict_data-operation-button'}:
dict_code = int(','.join(selected_row_keys))
@@ -208,117 +249,112 @@ def add_edit_dict_data_modal(operation_click, button_click, selected_row_keys, c
dict_data_info_res = get_dict_data_detail_api(dict_code=dict_code)
if dict_data_info_res['code'] == 200:
dict_data_info = dict_data_info_res['data']
- return [
- True,
- '编辑字典数据',
- dict_data_info.get('dict_type'),
- dict_data_info.get('dict_label'),
- dict_data_info.get('dict_value'),
- dict_data_info.get('css_class'),
- dict_data_info.get('dict_sort'),
- dict_data_info.get('list_class'),
- dict_data_info.get('status'),
- dict_data_info.get('remark'),
- {'timestamp': time.time()},
- dict_data_info if dict_data_info else None,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 10 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑字典数据',
+ form_value=[dict_data_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=dict_data_info if dict_data_info else None,
+ modal_type={'type': 'edit'}
+ )
+
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
- return [dash.no_update] * 11 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('dict_data-dict_label-form-item', 'validateStatus'),
- Output('dict_data-dict_value-form-item', 'validateStatus'),
- Output('dict_data-dict_sort-form-item', 'validateStatus'),
- Output('dict_data-dict_label-form-item', 'help'),
- Output('dict_data-dict_value-form-item', 'help'),
- Output('dict_data-dict_sort-form-item', 'help'),
- Output('dict_data-modal', 'visible'),
- Output('dict_data-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('dict_data-modal', 'okCounts'),
- [State('dict_data-operations-store-bk', 'data'),
- State('dict_data-edit-id-store', 'data'),
- State('dict_data-dict_type', 'value'),
- State('dict_data-dict_label', 'value'),
- State('dict_data-dict_value', 'value'),
- State('dict_data-css_class', 'value'),
- State('dict_data-dict_sort', 'value'),
- State('dict_data-list_class', 'value'),
- State('dict_data-status', 'value'),
- State('dict_data-remark', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'dict_data-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'dict_data-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('dict_data-modal', 'visible'),
+ operations=Output('dict_data-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('dict_data-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('dict_data-operations-store-bk', 'data'),
+ edit_row_info=State('dict_data-edit-id-store', 'data'),
+ form_value=State({'type': 'dict_data-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'dict_data-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def dict_data_confirm(confirm_trigger, operation_type, cur_post_info, dict_type, dict_label, dict_value, css_class, dict_sort, list_class, status, remark):
+def dict_data_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label):
+ """
+ 新增或编字典数据弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([dict_label, dict_value, dict_sort]):
- params_add = dict(dict_type=dict_type, dict_label=dict_label, dict_value=dict_value, css_class=css_class, dict_sort=dict_sort, list_class=list_class, status=status, remark=remark)
- params_edit = dict(dict_code=cur_post_info.get('dict_code') if cur_post_info else None, dict_type=dict_type, dict_label=dict_label, dict_value=dict_value, css_class=css_class, dict_sort=dict_sort, list_class=list_class, status=status, remark=remark)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params_add = form_value_state
+ params_edit = params_add.copy()
+ params_edit['dict_code'] = edit_row_info.get('dict_code') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_dict_data_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_dict_data_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [
- None if dict_label else 'error',
- None if dict_value else 'error',
- None if dict_sort else 'error',
- None if dict_label else '请输入数据标签!',
- None if dict_value else '请输入数据键值!',
- None if dict_sort else '请输入显示排序!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 10
+ raise PreventUpdate
@app.callback(
@@ -334,6 +370,9 @@ def dict_data_confirm(confirm_trigger, operation_type, cur_post_info, dict_type,
)
def dict_data_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除字典数据二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'dict_data-operation-button'} or (
trigger_id == 'dict_data-list-table' and clicked_content == '删除'):
@@ -352,7 +391,7 @@ def dict_data_delete_modal(operation_click, button_click,
{'dict_codes': dict_codes}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -364,6 +403,9 @@ def dict_data_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def dict_data_delete_confirm(delete_confirm, dict_codes_data):
+ """
+ 删除字典数据弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = dict_codes_data
@@ -381,7 +423,7 @@ def dict_data_delete_confirm(delete_confirm, dict_codes_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -394,6 +436,9 @@ def dict_data_delete_confirm(delete_confirm, dict_codes_data):
prevent_initial_call=True
)
def export_dict_data_list(export_click, dict_type):
+ """
+ 导出字典数据信息回调
+ """
if export_click:
export_dict_data_res = export_dict_data_list_api(dict(dict_type=dict_type))
if export_dict_data_res.status_code == 200:
@@ -413,7 +458,7 @@ def export_dict_data_list(export_click, dict_type):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -422,9 +467,12 @@ def export_dict_data_list(export_click, dict_type):
prevent_initial_call=True
)
def reset_dict_data_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/button_type_c.py b/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/button_type_c.py
index 773a70d2ab4df2ed7f05af3a7e3b2046ccb88cca..53da181b9c4b5e6a0845201ea350138062f59f27 100644
--- a/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/button_type_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/button_type_c.py
@@ -1,6 +1,7 @@
import dash
import time
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -8,94 +9,92 @@ from api.menu import add_menu_api, edit_menu_api
@app.callback(
- [Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
- Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
- Output('menu-order_num-form-item', 'help', allow_duplicate=True),
- Output('menu-modal', 'visible', allow_duplicate=True),
- Output('menu-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('menu-modal-F-trigger', 'data'),
- [State('menu-operations-store-bk', 'data'),
- State('menu-edit-id-store', 'data'),
- State('menu-parent_id', 'value'),
- State('menu-menu_type', 'value'),
- State('menu-icon', 'value'),
- State('menu-menu_name', 'value'),
- State('menu-order_num', 'value'),
- State('button-menu-perms', 'value')],
+ output=dict(
+ form_validate=[
+ Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'help', allow_duplicate=True)
+ ],
+ modal_visible=Output('menu-modal', 'visible', allow_duplicate=True),
+ operations=Output('menu-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('menu-modal-F-trigger', 'data'),
+ ),
+ state=dict(
+ modal_type=State('menu-operations-store-bk', 'data'),
+ edit_row_info=State('menu-edit-id-store', 'data'),
+ parent_id=State('menu-parent_id', 'value'),
+ menu_type=State('menu-menu_type', 'value'),
+ icon=State('menu-icon', 'value'),
+ menu_name=State('menu-menu_name', 'value'),
+ order_num=State('menu-order_num', 'value'),
+ perms=State('button-menu-perms', 'value')
+ ),
prevent_initial_call=True
)
-def menu_confirm_button(confirm_trigger, operation_type, cur_menu_info, parent_id, menu_type, icon, menu_name, order_num, perms):
+def menu_confirm_button(confirm_trigger, modal_type, edit_row_info, parent_id, menu_type, icon, menu_name, order_num, perms):
+ """
+ 菜单类型为按钮时新增或编辑弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
if all([parent_id, menu_name, order_num]):
params_add = dict(parent_id=parent_id, menu_type=menu_type, icon=icon, menu_name=menu_name, order_num=order_num, perms=perms)
- params_edit = dict(menu_id=cur_menu_info.get('menu_id') if cur_menu_info else None, parent_id=parent_id, menu_type=menu_type, icon=icon,
+ params_edit = dict(menu_id=edit_row_info.get('menu_id') if edit_row_info else None, parent_id=parent_id, menu_type=menu_type, icon=icon,
menu_name=menu_name, order_num=order_num, perms=perms)
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_menu_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_menu_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
-
- return [
- None if parent_id else 'error',
- None if menu_name else 'error',
- None if order_num else 'error',
- None if parent_id else '请选择上级菜单!',
- None if menu_name else '请输入菜单名称!',
- None if order_num else '请输入显示排序!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_validate=[None] * 6,
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_validate=[None] * 6,
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
- return [dash.no_update] * 10
+ return dict(
+ form_validate=[None] * 6,
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ return dict(
+ form_validate=[
+ None if parent_id else 'error',
+ None if menu_name else 'error',
+ None if order_num else 'error',
+ None if parent_id else '请选择上级菜单!',
+ None if menu_name else '请输入菜单名称!',
+ None if order_num else '请输入显示排序!'
+ ],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ raise PreventUpdate
@app.callback(
@@ -103,7 +102,10 @@ def menu_confirm_button(confirm_trigger, operation_type, cur_menu_info, parent_i
Input('menu-edit-id-store', 'data')
)
def set_edit_info(edit_info):
+ """
+ 菜单类型为按钮时回显菜单数据回调
+ """
if edit_info:
return edit_info.get('perms')
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/content_type_c.py b/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/content_type_c.py
index 4b692103102f2895543edb825be8d0625b7e3d48..d18c71630026c0293bc6514de8879b13b652c9d6 100644
--- a/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/content_type_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/content_type_c.py
@@ -1,6 +1,7 @@
import dash
import time
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -8,108 +9,100 @@ from api.menu import add_menu_api, edit_menu_api
@app.callback(
- [Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
- Output('content-menu-path-form-item', 'validateStatus'),
- Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
- Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
- Output('menu-order_num-form-item', 'help', allow_duplicate=True),
- Output('content-menu-path-form-item', 'help'),
- Output('menu-modal', 'visible', allow_duplicate=True),
- Output('menu-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('menu-modal-M-trigger', 'data'),
- [State('menu-operations-store-bk', 'data'),
- State('menu-edit-id-store', 'data'),
- State('menu-parent_id', 'value'),
- State('menu-menu_type', 'value'),
- State('menu-icon', 'value'),
- State('menu-menu_name', 'value'),
- State('menu-order_num', 'value'),
- State('content-menu-is_frame', 'value'),
- State('content-menu-path', 'value'),
- State('content-menu-visible', 'value'),
- State('content-menu-status', 'value')],
+ output=dict(
+ form_validate=[
+ Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
+ Output('content-menu-path-form-item', 'validateStatus'),
+ Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'help', allow_duplicate=True),
+ Output('content-menu-path-form-item', 'help'),
+ ],
+ modal_visible=Output('menu-modal', 'visible', allow_duplicate=True),
+ operations=Output('menu-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('menu-modal-M-trigger', 'data')
+ ),
+ state=dict(
+ modal_type=State('menu-operations-store-bk', 'data'),
+ edit_row_info=State('menu-edit-id-store', 'data'),
+ parent_id=State('menu-parent_id', 'value'),
+ menu_type=State('menu-menu_type', 'value'),
+ icon=State('menu-icon', 'value'),
+ menu_name=State('menu-menu_name', 'value'),
+ order_num=State('menu-order_num', 'value'),
+ is_frame=State('content-menu-is_frame', 'value'),
+ path=State('content-menu-path', 'value'),
+ visible=State('content-menu-visible', 'value'),
+ status=State('content-menu-status', 'value')
+ ),
prevent_initial_call=True
)
-def menu_confirm_content(confirm_trigger, operation_type, cur_menu_info, parent_id, menu_type, icon, menu_name, order_num, is_frame, path, visible, status):
+def menu_confirm_content(confirm_trigger, modal_type, edit_row_info, parent_id, menu_type, icon, menu_name, order_num, is_frame, path, visible, status):
+ """
+ 菜单类型为目录时新增或编辑弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
if all([parent_id, menu_name, order_num, path]):
params_add = dict(parent_id=parent_id, menu_type=menu_type, icon=icon, menu_name=menu_name, order_num=order_num,
is_frame=is_frame, path=path, visible=visible, status=status)
- params_edit = dict(menu_id=cur_menu_info.get('menu_id') if cur_menu_info else None, parent_id=parent_id, menu_type=menu_type, icon=icon,
+ params_edit = dict(menu_id=edit_row_info.get('menu_id') if edit_row_info else None, parent_id=parent_id, menu_type=menu_type, icon=icon,
menu_name=menu_name, order_num=order_num, is_frame=is_frame, path=path, visible=visible, status=status)
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_menu_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_menu_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
-
- return [
- None if parent_id else 'error',
- None if menu_name else 'error',
- None if order_num else 'error',
- None if path else 'error',
- None if parent_id else '请选择上级菜单!',
- None if menu_name else '请输入菜单名称!',
- None if order_num else '请输入显示排序!',
- None if path else '请输入路由地址!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_validate=[None] * 8,
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_validate=[None] * 8,
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_validate=[None] * 8,
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ return dict(
+ form_validate=[
+ None if parent_id else 'error',
+ None if menu_name else 'error',
+ None if order_num else 'error',
+ None if path else 'error',
+ None if parent_id else '请选择上级菜单!',
+ None if menu_name else '请输入菜单名称!',
+ None if order_num else '请输入显示排序!',
+ None if path else '请输入路由地址!',
+ ],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 12
+ raise PreventUpdate
@app.callback(
@@ -120,6 +113,9 @@ def menu_confirm_content(confirm_trigger, operation_type, cur_menu_info, parent_
Input('menu-edit-id-store', 'data')
)
def set_edit_info(edit_info):
+ """
+ 菜单类型为目录时回显菜单数据回调
+ """
if edit_info:
return [
edit_info.get('is_frame'),
@@ -128,4 +124,4 @@ def set_edit_info(edit_info):
edit_info.get('status')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/menu_type_c.py b/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/menu_type_c.py
index 5ca9d4a7f96e6396f7eace93fd8ebe72cf018d7c..f37b79231973b06560bdb14fdd2e761dbd836edb 100644
--- a/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/menu_type_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/menu_c/components_c/menu_type_c.py
@@ -1,6 +1,7 @@
import dash
import time
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -8,114 +9,106 @@ from api.menu import add_menu_api, edit_menu_api
@app.callback(
- [Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
- Output('menu-menu-path-form-item', 'validateStatus'),
- Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
- Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
- Output('menu-order_num-form-item', 'help', allow_duplicate=True),
- Output('menu-menu-path-form-item', 'help', allow_duplicate=True),
- Output('menu-modal', 'visible'),
- Output('menu-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('menu-modal-C-trigger', 'data'),
- [State('menu-operations-store-bk', 'data'),
- State('menu-edit-id-store', 'data'),
- State('menu-parent_id', 'value'),
- State('menu-menu_type', 'value'),
- State('menu-icon', 'value'),
- State('menu-menu_name', 'value'),
- State('menu-order_num', 'value'),
- State('menu-menu-is_frame', 'value'),
- State('menu-menu-path', 'value'),
- State('menu-menu-component', 'value'),
- State('menu-menu-perms', 'value'),
- State('menu-menu-query', 'value'),
- State('menu-menu-is_cache', 'value'),
- State('menu-menu-visible', 'value'),
- State('menu-menu-status', 'value')],
+ output=dict(
+ form_validate=[
+ Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-menu-path-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'help', allow_duplicate=True),
+ Output('menu-menu-path-form-item', 'help', allow_duplicate=True),
+ ],
+ modal_visible=Output('menu-modal', 'visible', allow_duplicate=True),
+ operations=Output('menu-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('menu-modal-C-trigger', 'data')
+ ),
+ state=dict(
+ modal_type=State('menu-operations-store-bk', 'data'),
+ edit_row_info=State('menu-edit-id-store', 'data'),
+ parent_id=State('menu-parent_id', 'value'),
+ menu_type=State('menu-menu_type', 'value'),
+ icon=State('menu-icon', 'value'),
+ menu_name=State('menu-menu_name', 'value'),
+ order_num=State('menu-order_num', 'value'),
+ is_frame=State('menu-menu-is_frame', 'value'),
+ path=State('menu-menu-path', 'value'),
+ component=State('menu-menu-component', 'value'),
+ perms=State('menu-menu-perms', 'value'),
+ query=State('menu-menu-query', 'value'),
+ is_cache=State('menu-menu-is_cache', 'value'),
+ visible=State('menu-menu-visible', 'value'),
+ status=State('menu-menu-status', 'value')
+ ),
prevent_initial_call=True
)
-def menu_confirm_menu(confirm_trigger, operation_type, cur_menu_info, parent_id, menu_type, icon, menu_name, order_num, is_frame, path,
+def menu_confirm_menu(confirm_trigger, modal_type, edit_row_info, parent_id, menu_type, icon, menu_name, order_num, is_frame, path,
component, perms, query, is_cache, visible, status):
+ """
+ 菜单类型为菜单时新增或编辑弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
if all([parent_id, menu_name, order_num, path]):
params_add = dict(parent_id=parent_id, menu_type=menu_type, icon=icon, menu_name=menu_name, order_num=order_num, is_frame=is_frame,
path=path, component=component, perms=perms, query=query, is_cache=is_cache, visible=visible, status=status)
- params_edit = dict(menu_id=cur_menu_info.get('menu_id') if cur_menu_info else None, parent_id=parent_id, menu_type=menu_type, icon=icon,
+ params_edit = dict(menu_id=edit_row_info.get('menu_id') if edit_row_info else None, parent_id=parent_id, menu_type=menu_type, icon=icon,
menu_name=menu_name, order_num=order_num, is_frame=is_frame, path=path, component=component,
perms=perms, query=query, is_cache=is_cache, visible=visible, status=status)
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_menu_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_menu_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
-
- return [
- None if parent_id else 'error',
- None if menu_name else 'error',
- None if order_num else 'error',
- None if path else 'error',
- None if parent_id else '请选择上级菜单!',
- None if menu_name else '请输入菜单名称!',
- None if order_num else '请输入显示排序!',
- None if path else '请输入路由地址!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_validate=[None] * 8,
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_validate=[None] * 8,
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_validate=[None] * 8,
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ return dict(
+ form_validate=[
+ None if parent_id else 'error',
+ None if menu_name else 'error',
+ None if order_num else 'error',
+ None if path else 'error',
+ None if parent_id else '请选择上级菜单!',
+ None if menu_name else '请输入菜单名称!',
+ None if order_num else '请输入显示排序!',
+ None if path else '请输入路由地址!'
+ ],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 12
+ raise PreventUpdate
@app.callback(
@@ -130,6 +123,9 @@ def menu_confirm_menu(confirm_trigger, operation_type, cur_menu_info, parent_id,
Input('menu-edit-id-store', 'data')
)
def set_edit_info(edit_info):
+ """
+ 菜单类型为菜单时回显菜单数据回调
+ """
if edit_info:
return [
edit_info.get('is_frame'),
@@ -142,4 +138,4 @@ def set_edit_info(edit_info):
edit_info.get('status')
]
- return [dash.no_update] * 8
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/menu_c/menu_c.py b/dash-fastapi-frontend/callbacks/system_c/menu_c/menu_c.py
index de196db92fb53d4bcde5cbbf976f6c61b9376c8e..dfcdedd7c464005b753eb268fb866359596840c8 100644
--- a/dash-fastapi-frontend/callbacks/system_c/menu_c/menu_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/menu_c/menu_c.py
@@ -2,6 +2,7 @@ import dash
import time
import uuid
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_antd_components as fac
import feffery_utils_components as fuc
@@ -12,22 +13,31 @@ from api.menu import get_menu_tree_api, get_menu_tree_for_edit_option_api, get_m
@app.callback(
- [Output('menu-list-table', 'data', allow_duplicate=True),
- Output('menu-list-table', 'key'),
- Output('menu-list-table', 'defaultExpandedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('menu-fold', 'nClicks')],
- [Input('menu-search', 'nClicks'),
- Input('menu-refresh', 'nClicks'),
- Input('menu-operations-store', 'data'),
- Input('menu-fold', 'nClicks')],
- [State('menu-menu_name-input', 'value'),
- State('menu-status-select', 'value'),
- State('menu-list-table', 'defaultExpandedRowKeys'),
- State('menu-button-perms-container', 'data')],
+ output=dict(
+ menu_table_data=Output('menu-list-table', 'data', allow_duplicate=True),
+ menu_table_key=Output('menu-list-table', 'key'),
+ menu_table_defaultexpandedrowkeys=Output('menu-list-table', 'defaultExpandedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ fold_click=Output('menu-fold', 'nClicks')
+ ),
+ inputs=dict(
+ search_click=Input('menu-search', 'nClicks'),
+ refresh_click=Input('menu-refresh', 'nClicks'),
+ operations=Input('menu-operations-store', 'data'),
+ fold_click=Input('menu-fold', 'nClicks')
+ ),
+ state=dict(
+ menu_name=State('menu-menu_name-input', 'value'),
+ status_select=State('menu-status-select', 'value'),
+ in_default_expanded_row_keys=State('menu-list-table', 'defaultExpandedRowKeys'),
+ button_perms=State('menu-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_menu_table_data(search_click, refresh_click, operations, fold_click, menu_name, status_select, in_default_expanded_row_keys, button_perms):
+ """
+ 获取菜单表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
menu_name=menu_name,
@@ -90,15 +100,40 @@ def get_menu_table_data(search_click, refresh_click, operations, fold_click, men
if fold_click:
if not in_default_expanded_row_keys:
- return [table_data_new, str(uuid.uuid4()), default_expanded_row_keys, {'timestamp': time.time()}, None]
-
- return [table_data_new, str(uuid.uuid4()), [], {'timestamp': time.time()}, None]
-
- return [dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}, None]
-
- return [dash.no_update] * 4 + [None]
+ return dict(
+ menu_table_data=table_data_new,
+ menu_table_key=str(uuid.uuid4()),
+ menu_table_defaultexpandedrowkeys=default_expanded_row_keys,
+ api_check_token_trigger={'timestamp': time.time()},
+ fold_click=None
+ )
+
+ return dict(
+ menu_table_data=table_data_new,
+ menu_table_key=str(uuid.uuid4()),
+ menu_table_defaultexpandedrowkeys=[],
+ api_check_token_trigger={'timestamp': time.time()},
+ fold_click=None
+ )
+
+ return dict(
+ menu_table_data=dash.no_update,
+ menu_table_key=dash.no_update,
+ menu_table_defaultexpandedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ fold_click=None
+ )
+
+ return dict(
+ menu_table_data=dash.no_update,
+ menu_table_key=dash.no_update,
+ menu_table_defaultexpandedrowkeys=dash.no_update,
+ api_check_token_trigger=dash.no_update,
+ fold_click=None
+ )
+# 重置菜单搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -116,6 +151,7 @@ app.clientside_callback(
)
+# 隐藏/显示菜单搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -143,36 +179,55 @@ app.clientside_callback(
prevent_initial_call=True
)
def get_select_icon(icon):
+ """
+ 获取新增或编辑表单中选择的icon回调
+ """
if icon:
return [
icon,
fac.AntdIcon(icon=icon)
]
- return [dash.no_update] * 2
-
+ raise PreventUpdate
@app.callback(
- [Output('menu-modal', 'visible', allow_duplicate=True),
- Output('menu-modal', 'title'),
- Output('menu-parent_id', 'treeData'),
- Output('menu-parent_id', 'value'),
- Output('menu-menu_type', 'value'),
- Output('menu-icon', 'value', allow_duplicate=True),
- Output('menu-icon', 'prefix', allow_duplicate=True),
- Output('menu-menu_name', 'value'),
- Output('menu-order_num', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('menu-edit-id-store', 'data'),
- Output('menu-operations-store-bk', 'data')],
- [Input({'type': 'menu-operation-button', 'index': ALL}, 'nClicks'),
- Input('menu-list-table', 'nClicksButton')],
- [State('menu-list-table', 'clickedContent'),
- State('menu-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal=dict(visible=Output('menu-modal', 'visible', allow_duplicate=True), title=Output('menu-modal', 'title')),
+ form_value=dict(
+ parent_tree=Output('menu-parent_id', 'treeData'), parent_id=Output('menu-parent_id', 'value'),
+ menu_type=Output('menu-menu_type', 'value'), icon=Output('menu-icon', 'value', allow_duplicate=True),
+ icon_prefix=Output('menu-icon', 'prefix', allow_duplicate=True), icon_category=Output('icon-category', 'value'),
+ menu_name=Output('menu-menu_name', 'value'), order_num=Output('menu-order_num', 'value')
+ ),
+ form_validate=[
+ Output('menu-parent_id-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'validateStatus', allow_duplicate=True),
+ Output('menu-parent_id-form-item', 'help', allow_duplicate=True),
+ Output('menu-menu_name-form-item', 'help', allow_duplicate=True),
+ Output('menu-order_num-form-item', 'help', allow_duplicate=True)
+ ],
+ other=dict(
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('menu-edit-id-store', 'data'),
+ modal_type=Output('menu-operations-store-bk', 'data')
+ )
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'menu-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('menu-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ clicked_content=State('menu-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('menu-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_menu_modal(operation_click, button_click, clicked_content, recently_button_clicked_row):
+ """
+ 显示新增或编辑菜单弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'menu-operation-button'} or (trigger_id == 'menu-list-table' and clicked_content != '删除'):
menu_params = dict(menu_name='')
@@ -184,58 +239,70 @@ def add_edit_menu_modal(operation_click, button_click, clicked_content, recently
tree_data = tree_info['data']
if trigger_id == {'index': 'add', 'type': 'menu-operation-button'}:
- return [
- True,
- '新增菜单',
- tree_data,
- '0',
- 'M',
- None,
- None,
- None,
- None,
- {'timestamp': time.time()},
- None,
- {'type': 'add'}
- ]
+ return dict(
+ modal=dict(visible=True, title='新增菜单'),
+ form_value=dict(
+ parent_tree=tree_data, parent_id='0', menu_type='M', icon=None,
+ icon_prefix=None, icon_category=None, menu_name=None, order_num=None
+ ),
+ form_validate=[None] * 6,
+ other=dict(
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
+ )
elif trigger_id == 'menu-list-table' and clicked_content == '新增':
- return [
- True,
- '新增菜单',
- tree_data,
- str(recently_button_clicked_row['key']),
- 'M',
- None,
- None,
- None,
- None,
- {'timestamp': time.time()},
- None,
- {'type': 'add'}
- ]
+ return dict(
+ modal=dict(visible=True, title='新增菜单'),
+ form_value=dict(
+ parent_tree=tree_data, parent_id=str(recently_button_clicked_row['key']), menu_type='M',
+ icon=None, icon_prefix=None, icon_category=None, menu_name=None, order_num=None
+ ),
+ form_validate=[None] * 6,
+ other=dict(
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
+ )
elif trigger_id == 'menu-list-table' and clicked_content == '修改':
menu_id = int(recently_button_clicked_row['key'])
menu_info_res = get_menu_detail_api(menu_id=menu_id)
if menu_info_res['code'] == 200:
menu_info = menu_info_res['data']
- return [
- True,
- '编辑菜单',
- tree_data,
- str(menu_info.get('parent_id')),
- menu_info.get('menu_type'),
- menu_info.get('icon'),
- fac.AntdIcon(icon=menu_info.get('icon')),
- menu_info.get('menu_name'),
- menu_info.get('order_num'),
- {'timestamp': time.time()},
- menu_info,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 9 + [{'timestamp': time.time()}, None, None]
-
- return [dash.no_update] * 10 + [None, None]
+ return dict(
+ modal=dict(visible=True, title='编辑菜单'),
+ form_value=dict(
+ parent_tree=tree_data, parent_id=str(menu_info.get('parent_id')),
+ menu_type=menu_info.get('menu_type'), icon=menu_info.get('icon'),
+ icon_prefix=fac.AntdIcon(icon=menu_info.get('icon')), icon_category=menu_info.get('icon'),
+ menu_name=menu_info.get('menu_name'), order_num=menu_info.get('order_num')
+ ),
+ form_validate=[None] * 6,
+ other=dict(
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=menu_info,
+ modal_type={'type': 'edit'}
+ )
+ )
+
+ return dict(
+ modal=dict(visible=dash.no_update, title=dash.no_update),
+ form_value=dict(
+ parent_tree=dash.no_update, parent_id=dash.no_update, menu_type=dash.no_update,
+ icon=dash.no_update, icon_prefix=dash.no_update, icon_category=dash.no_update,
+ menu_name=dash.no_update, order_num=dash.no_update
+ ),
+ form_validate=[dash.no_update] * 6,
+ other=dict(
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
+ )
+
+ raise PreventUpdate
@app.callback(
@@ -258,7 +325,7 @@ def get_bottom_content(menu_value):
elif menu_value == 'F':
return [button_type.render(), str(uuid.uuid4()), {'type': 'F'}]
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -293,7 +360,7 @@ def modal_confirm_trigger(confirm, menu_type):
{'timestamp': time.time()}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -306,6 +373,9 @@ def modal_confirm_trigger(confirm, menu_type):
prevent_initial_call=True
)
def menu_delete_modal(button_click, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除菜单二次确认弹窗回调
+ """
if button_click:
if clicked_content == '删除':
@@ -319,7 +389,7 @@ def menu_delete_modal(button_click, clicked_content, recently_button_clicked_row
{'menu_ids': menu_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -331,6 +401,9 @@ def menu_delete_modal(button_click, clicked_content, recently_button_clicked_row
prevent_initial_call=True
)
def menu_delete_confirm(delete_confirm, menu_ids_data):
+ """
+ 删除菜单弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = menu_ids_data
@@ -348,4 +421,4 @@ def menu_delete_confirm(delete_confirm, menu_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/notice_c.py b/dash-fastapi-frontend/callbacks/system_c/notice_c.py
index 953deeb02c9ec67f75eb1c76911743c90c4e29a7..accdfd307c2fb8589f00f320f414439fc60c6518 100644
--- a/dash-fastapi-frontend/callbacks/system_c/notice_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/notice_c.py
@@ -5,6 +5,7 @@ import re
import json
from flask import session
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -14,24 +15,33 @@ from api.dict import query_dict_data_list_api
@app.callback(
- [Output('notice-list-table', 'data', allow_duplicate=True),
- Output('notice-list-table', 'pagination', allow_duplicate=True),
- Output('notice-list-table', 'key'),
- Output('notice-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('notice-search', 'nClicks'),
- Input('notice-refresh', 'nClicks'),
- Input('notice-list-table', 'pagination'),
- Input('notice-operations-store', 'data')],
- [State('notice-notice_title-input', 'value'),
- State('notice-update_by-input', 'value'),
- State('notice-notice_type-select', 'value'),
- State('notice-create_time-range', 'value'),
- State('notice-button-perms-container', 'data')],
+ output=dict(
+ notice_table_data=Output('notice-list-table', 'data', allow_duplicate=True),
+ notice_table_pagination=Output('notice-list-table', 'pagination', allow_duplicate=True),
+ notice_table_key=Output('notice-list-table', 'key'),
+ notice_table_selectedrowkeys=Output('notice-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('notice-search', 'nClicks'),
+ refresh_click=Input('notice-refresh', 'nClicks'),
+ pagination=Input('notice-list-table', 'pagination'),
+ operations=Input('notice-operations-store', 'data')
+ ),
+ state=dict(
+ notice_title=State('notice-notice_title-input', 'value'),
+ update_by=State('notice-update_by-input', 'value'),
+ notice_type=State('notice-notice_type-select', 'value'),
+ create_time_range=State('notice-create_time-range', 'value'),
+ button_perms=State('notice-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_notice_table_data(search_click, refresh_click, pagination, operations, notice_title, update_by, notice_type, create_time_range,
button_perms):
+ """
+ 获取通知公告表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
create_time_start = None
create_time_end = None
if create_time_range:
@@ -102,13 +112,26 @@ def get_notice_table_data(search_click, refresh_click, pagination, operations, n
} if 'system:notice:remove' in button_perms else {},
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ notice_table_data=table_data,
+ notice_table_pagination=table_pagination,
+ notice_table_key=str(uuid.uuid4()),
+ notice_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ notice_table_data=dash.no_update,
+ notice_table_pagination=dash.no_update,
+ notice_table_key=dash.no_update,
+ notice_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置通知公告搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -128,6 +151,7 @@ app.clientside_callback(
)
+# 隐藏/显示通知公告搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -154,6 +178,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_notice_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -164,7 +191,7 @@ def change_notice_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -173,17 +200,18 @@ def change_notice_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_notice_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -192,6 +220,9 @@ def change_notice_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def init_render_editor(html_string):
+ """
+ 初始化富文本编辑器回调
+ """
url = f'{ApiBaseUrlConfig.BaseUrl}/common/uploadForEditor'
token = 'Bearer ' + session.get('Authorization')
@@ -286,40 +317,57 @@ def init_render_editor(html_string):
@app.callback(
- [Output('notice-modal', 'visible', allow_duplicate=True),
- Output('notice-modal', 'title'),
- Output('notice-notice_title', 'value'),
- Output('notice-notice_type', 'value'),
- Output('notice-status', 'value'),
- Output('notice-written-editor-store', 'data'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('notice-edit-id-store', 'data'),
- Output('notice-operations-store-bk', 'data')],
- [Input({'type': 'notice-operation-button', 'index': ALL}, 'nClicks'),
- Input('notice-list-table', 'nClicksButton')],
- [State('notice-list-table', 'selectedRowKeys'),
- State('notice-list-table', 'clickedContent'),
- State('notice-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal=dict(visible=Output('notice-modal', 'visible', allow_duplicate=True), title=Output('notice-modal', 'title')),
+ form_value=dict(
+ notice_title=Output('notice-notice_title', 'value'),
+ notice_type=Output('notice-notice_type', 'value'),
+ status=Output('notice-status', 'value'),
+ editor_content=Output('notice-written-editor-store', 'data'),
+ ),
+ form_validate=[
+ Output('notice-notice_title-form-item', 'validateStatus', allow_duplicate=True),
+ Output('notice-notice_type-form-item', 'validateStatus', allow_duplicate=True),
+ Output('notice-notice_title-form-item', 'help', allow_duplicate=True),
+ Output('notice-notice_type-form-item', 'help', allow_duplicate=True)
+ ],
+ other=dict(
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('notice-edit-id-store', 'data'),
+ modal_type=Output('notice-operations-store-bk', 'data')
+ )
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'notice-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('notice-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ selected_row_keys=State('notice-list-table', 'selectedRowKeys'),
+ clicked_content=State('notice-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('notice-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_notice_modal(operation_click, button_click, selected_row_keys, clicked_content,
recently_button_clicked_row):
+ """
+ 显示新增或编辑通知公告弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'notice-operation-button'} \
or trigger_id == {'index': 'edit', 'type': 'notice-operation-button'} \
or (trigger_id == 'notice-list-table' and clicked_content == '修改'):
if trigger_id == {'index': 'add', 'type': 'notice-operation-button'}:
- return [
- True,
- '新增通知公告',
- None,
- None,
- '0',
- '
',
- dash.no_update,
- None,
- {'type': 'add'}
- ]
+ return dict(
+ modal=dict(visible=True, title='新增通知公告'),
+ form_value=dict(notice_title=None, notice_type=None, status='0', editor_content='
'),
+ form_validate=[None] * 4,
+ other=dict(
+ api_check_token_trigger=dash.no_update,
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
+ )
elif trigger_id == {'index': 'edit', 'type': 'notice-operation-button'} or (trigger_id == 'notice-list-table' and clicked_content == '修改'):
if trigger_id == {'index': 'edit', 'type': 'notice-operation-button'}:
notice_id = int(','.join(selected_row_keys))
@@ -330,102 +378,129 @@ def add_edit_notice_modal(operation_click, button_click, selected_row_keys, clic
notice_info = notice_info_res['data']
notice_content = notice_info.get('notice_content')
- return [
- True,
- '编辑通知公告',
- notice_info.get('notice_title'),
- notice_info.get('notice_type'),
- notice_info.get('status'),
- re.sub(r"\n", "", notice_content),
- {'timestamp': time.time()},
- notice_info if notice_info else None,
- {'type': 'edit'}
- ]
+ return dict(
+ modal=dict(visible=True, title='编辑通知公告'),
+ form_value=dict(
+ notice_title=notice_info.get('notice_title'),
+ notice_type=notice_info.get('notice_type'),
+ status=notice_info.get('status'),
+ editor_content=re.sub(r"\n", "", notice_content)
+ ),
+ form_validate=[None] * 4,
+ other=dict(
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=notice_info if notice_info else None,
+ modal_type={'type': 'edit'}
+ )
+ )
- return [dash.no_update] * 6 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal=dict(visible=dash.no_update, title=dash.no_update),
+ form_value=dict(
+ notice_title=dash.no_update,
+ notice_type=dash.no_update,
+ status=dash.no_update,
+ editor_content=dash.no_update
+ ),
+ form_validate=[dash.no_update] * 4,
+ other=dict(
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
+ )
- return [dash.no_update] * 7 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('notice-notice_title-form-item', 'validateStatus'),
- Output('notice-notice_type-form-item', 'validateStatus'),
- Output('notice-notice_title-form-item', 'help'),
- Output('notice-notice_type-form-item', 'help'),
- Output('notice-modal', 'visible'),
- Output('notice-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('notice-modal', 'okCounts'),
- [State('notice-operations-store-bk', 'data'),
- State('notice-edit-id-store', 'data'),
- State('notice-notice_title', 'value'),
- State('notice-notice_type', 'value'),
- State('notice-status', 'value'),
- State('notice-content', 'data')],
+ output=dict(
+ notice_title_form_status=Output('notice-notice_title-form-item', 'validateStatus', allow_duplicate=True),
+ notice_type_form_status=Output('notice-notice_type-form-item', 'validateStatus', allow_duplicate=True),
+ notice_title_form_help=Output('notice-notice_title-form-item', 'help', allow_duplicate=True),
+ notice_type_form_help=Output('notice-notice_type-form-item', 'help', allow_duplicate=True),
+ modal_visible=Output('notice-modal', 'visible'),
+ operations=Output('notice-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('notice-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('notice-operations-store-bk', 'data'),
+ edit_row_info=State('notice-edit-id-store', 'data'),
+ notice_title=State('notice-notice_title', 'value'),
+ notice_type=State('notice-notice_type', 'value'),
+ status=State('notice-status', 'value'),
+ notice_content=State('notice-content', 'data')
+ ),
prevent_initial_call=True
)
-def notice_confirm(confirm_trigger, operation_type, cur_notice_info, notice_title, notice_type, status, notice_content):
+def notice_confirm(confirm_trigger, modal_type, edit_row_info, notice_title, notice_type, status, notice_content):
+ """
+ 新增或编辑通知公告弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
if all([notice_title, notice_type]):
params_add = dict(notice_title=notice_title, notice_type=notice_type, status=status,
notice_content=notice_content.get('html'))
- params_edit = dict(notice_id=cur_notice_info.get('notice_id') if cur_notice_info else None,
+ params_edit = dict(notice_id=edit_row_info.get('notice_id') if edit_row_info else None,
notice_title=notice_title,
notice_type=notice_type, status=status, notice_content=notice_content.get('html'))
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_notice_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_notice_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ notice_title_form_status=None,
+ notice_type_form_status=None,
+ notice_title_form_help=None,
+ notice_type_form_help=None,
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ notice_title_form_status=None,
+ notice_type_form_status=None,
+ notice_title_form_help=None,
+ notice_type_form_help=None,
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ notice_title_form_status=None,
+ notice_type_form_status=None,
+ notice_title_form_help=None,
+ notice_type_form_help=None,
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [
- None if notice_title else 'error',
- None if notice_type else 'error',
- None if notice_title else '请输入公告标题!',
- None if notice_type else '请输入公告类型!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ return dict(
+ notice_title_form_status=None if notice_title else 'error',
+ notice_type_form_status=None if notice_type else 'error',
+ notice_title_form_help=None if notice_title else '请输入公告标题!',
+ notice_type_form_help=None if notice_type else '请输入公告类型!',
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 8
+ raise PreventUpdate
@app.callback(
@@ -441,6 +516,9 @@ def notice_confirm(confirm_trigger, operation_type, cur_notice_info, notice_titl
)
def notice_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除通知公告二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'notice-operation-button'} or (
trigger_id == 'notice-list-table' and clicked_content == '删除'):
@@ -460,7 +538,7 @@ def notice_delete_modal(operation_click, button_click,
{'notice_ids': notice_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -472,6 +550,9 @@ def notice_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def notice_delete_confirm(delete_confirm, notice_ids_data):
+ """
+ 删除岗通知公告弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = notice_ids_data
@@ -489,4 +570,4 @@ def notice_delete_confirm(delete_confirm, notice_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/post_c.py b/dash-fastapi-frontend/callbacks/system_c/post_c.py
index 30c46dc28190d80bea6bb8fff2c7e60d79b83b4e..1f8985a4710a2765ff8878dbfe4aa4f78363a100 100644
--- a/dash-fastapi-frontend/callbacks/system_c/post_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/post_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -10,22 +11,31 @@ from api.post import get_post_list_api, get_post_detail_api, add_post_api, edit_
@app.callback(
- [Output('post-list-table', 'data', allow_duplicate=True),
- Output('post-list-table', 'pagination', allow_duplicate=True),
- Output('post-list-table', 'key'),
- Output('post-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('post-search', 'nClicks'),
- Input('post-refresh', 'nClicks'),
- Input('post-list-table', 'pagination'),
- Input('post-operations-store', 'data')],
- [State('post-post_code-input', 'value'),
- State('post-post_name-input', 'value'),
- State('post-status-select', 'value'),
- State('post-button-perms-container', 'data')],
+ output=dict(
+ post_table_data=Output('post-list-table', 'data', allow_duplicate=True),
+ post_table_pagination=Output('post-list-table', 'pagination', allow_duplicate=True),
+ post_table_key=Output('post-list-table', 'key'),
+ post_table_selectedrowkeys=Output('post-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('post-search', 'nClicks'),
+ refresh_click=Input('post-refresh', 'nClicks'),
+ pagination=Input('post-list-table', 'pagination'),
+ operations=Input('post-operations-store', 'data')
+ ),
+ state=dict(
+ post_code=State('post-post_code-input', 'value'),
+ post_name=State('post-post_name-input', 'value'),
+ status_select=State('post-status-select', 'value'),
+ button_perms=State('post-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_post_table_data(search_click, refresh_click, pagination, operations, post_code, post_name, status_select, button_perms):
+ """
+ 获取岗位表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
post_code=post_code,
@@ -73,14 +83,26 @@ def get_post_table_data(search_click, refresh_click, pagination, operations, pos
'icon': 'antd-delete'
} if 'system:post:remove' in button_perms else {},
]
+ return dict(
+ post_table_data=table_data,
+ post_table_pagination=table_pagination,
+ post_table_key=str(uuid.uuid4()),
+ post_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
-
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ post_table_data=dash.no_update,
+ post_table_pagination=dash.no_update,
+ post_table_key=dash.no_update,
+ post_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置岗位搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -99,6 +121,7 @@ app.clientside_callback(
)
+# 隐藏/显示岗位搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -125,6 +148,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_post_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -135,7 +161,7 @@ def change_post_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -144,55 +170,66 @@ def change_post_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_post_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
- [Output('post-modal', 'visible', allow_duplicate=True),
- Output('post-modal', 'title'),
- Output('post-post_name', 'value'),
- Output('post-post_code', 'value'),
- Output('post-post_sort', 'value'),
- Output('post-status', 'value'),
- Output('post-remark', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('post-edit-id-store', 'data'),
- Output('post-operations-store-bk', 'data')],
- [Input({'type': 'post-operation-button', 'index': ALL}, 'nClicks'),
- Input('post-list-table', 'nClicksButton')],
- [State('post-list-table', 'selectedRowKeys'),
- State('post-list-table', 'clickedContent'),
- State('post-list-table', 'recentlyButtonClickedRow')],
+ output=dict(
+ modal_visible=Output('post-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('post-modal', 'title'),
+ form_value=Output({'type': 'post-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'post-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'post-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('post-edit-id-store', 'data'),
+ modal_type=Output('post-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'post-operation-button', 'index': ALL}, 'nClicks'),
+ button_click=Input('post-list-table', 'nClicksButton')
+ ),
+ state=dict(
+ selected_row_keys=State('post-list-table', 'selectedRowKeys'),
+ clicked_content=State('post-list-table', 'clickedContent'),
+ recently_button_clicked_row=State('post-list-table', 'recentlyButtonClickedRow')
+ ),
prevent_initial_call=True
)
def add_edit_post_modal(operation_click, button_click, selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示新增或编辑岗位弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'add', 'type': 'post-operation-button'} \
or trigger_id == {'index': 'edit', 'type': 'post-operation-button'} \
or (trigger_id == 'post-list-table' and clicked_content == '修改'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
if trigger_id == {'index': 'add', 'type': 'post-operation-button'}:
- return [
- True,
- '新增岗位',
- None,
- None,
- 0,
- '0',
- None,
- dash.no_update,
- None,
- {'type': 'add'}
- ]
+ post_info = dict(post_name=None, post_code=None, post_sort=0, status='0', remark=None)
+ return dict(
+ modal_visible=True,
+ modal_title='新增岗位',
+ form_value=[post_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger=dash.no_update,
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id == {'index': 'edit', 'type': 'post-operation-button'} or (trigger_id == 'post-list-table' and clicked_content == '修改'):
if trigger_id == {'index': 'edit', 'type': 'post-operation-button'}:
post_id = int(','.join(selected_row_keys))
@@ -201,112 +238,112 @@ def add_edit_post_modal(operation_click, button_click, selected_row_keys, clicke
post_info_res = get_post_detail_api(post_id=post_id)
if post_info_res['code'] == 200:
post_info = post_info_res['data']
- return [
- True,
- '编辑岗位',
- post_info.get('post_name'),
- post_info.get('post_code'),
- post_info.get('post_sort'),
- post_info.get('status'),
- post_info.get('remark'),
- {'timestamp': time.time()},
- post_info if post_info else None,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 7 + [{'timestamp': time.time()}, None, None]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑岗位',
+ form_value=[post_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=post_info if post_info else None,
+ modal_type={'type': 'edit'}
+ )
+
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
- return [dash.no_update] * 8 + [None, None]
+ raise PreventUpdate
@app.callback(
- [Output('post-post_name-form-item', 'validateStatus'),
- Output('post-post_code-form-item', 'validateStatus'),
- Output('post-post_sort-form-item', 'validateStatus'),
- Output('post-post_name-form-item', 'help'),
- Output('post-post_code-form-item', 'help'),
- Output('post-post_sort-form-item', 'help'),
- Output('post-modal', 'visible'),
- Output('post-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('post-modal', 'okCounts'),
- [State('post-operations-store-bk', 'data'),
- State('post-edit-id-store', 'data'),
- State('post-post_name', 'value'),
- State('post-post_code', 'value'),
- State('post-post_sort', 'value'),
- State('post-status', 'value'),
- State('post-remark', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'post-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'post-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('post-modal', 'visible'),
+ operations=Output('post-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('post-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('post-operations-store-bk', 'data'),
+ edit_row_info=State('post-edit-id-store', 'data'),
+ form_value=State({'type': 'post-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'post-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def post_confirm(confirm_trigger, operation_type, cur_post_info, post_name, post_code, post_sort, status, remark):
+def post_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label):
+ """
+ 新增或编辑岗位弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([post_name, post_code, post_sort]):
- params_add = dict(post_name=post_name, post_code=post_code, post_sort=post_sort, status=status, remark=remark)
- params_edit = dict(post_id=cur_post_info.get('post_id') if cur_post_info else None, post_name=post_name,
- post_code=post_code, post_sort=post_sort, status=status, remark=remark)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params_add = form_value_state
+ params_edit = params_add.copy()
+ params_edit['post_id'] = edit_row_info.get('post_id') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_post_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_post_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
-
- return [
- None if post_name else 'error',
- None if post_code else 'error',
- None if post_sort else 'error',
- None if post_name else '请输入岗位名称!',
- None if post_code else '请输入岗位编码!',
- None if post_sort else '请输入岗位顺序!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
- return [dash.no_update] * 10
+ raise PreventUpdate
@app.callback(
@@ -322,6 +359,9 @@ def post_confirm(confirm_trigger, operation_type, cur_post_info, post_name, post
)
def post_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示删除岗位二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'post-operation-button'} or (trigger_id == 'post-list-table' and clicked_content == '删除'):
@@ -331,7 +371,7 @@ def post_delete_modal(operation_click, button_click,
if clicked_content == '删除':
post_ids = recently_button_clicked_row['key']
else:
- return dash.no_update
+ raise PreventUpdate
return [
f'是否确认删除岗位编号为{post_ids}的岗位?',
@@ -339,7 +379,7 @@ def post_delete_modal(operation_click, button_click,
{'post_ids': post_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -351,6 +391,9 @@ def post_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def post_delete_confirm(delete_confirm, post_ids_data):
+ """
+ 删除岗位弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = post_ids_data
@@ -368,7 +411,7 @@ def post_delete_confirm(delete_confirm, post_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -380,6 +423,9 @@ def post_delete_confirm(delete_confirm, post_ids_data):
prevent_initial_call=True
)
def export_post_list(export_click):
+ """
+ 导出岗位信息回调
+ """
if export_click:
export_post_res = export_post_list_api({})
if export_post_res.status_code == 200:
@@ -399,7 +445,7 @@ def export_post_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -408,9 +454,12 @@ def export_post_list(export_click):
prevent_initial_call=True
)
def reset_post_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/role_c/allocate_user_c.py b/dash-fastapi-frontend/callbacks/system_c/role_c/allocate_user_c.py
index 326839503d3778dea9dcf3ed8fab1b0f5901e5d7..9c3a9255fa031ad18056414e7c6e50d2d8120111 100644
--- a/dash-fastapi-frontend/callbacks/system_c/role_c/allocate_user_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/role_c/allocate_user_c.py
@@ -2,6 +2,7 @@ import dash
import time
import uuid
from dash.dependencies import Input, Output, State, ALL, MATCH
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -24,6 +25,9 @@ from api.role import get_allocated_user_list_api, get_unallocated_user_list_api,
prevent_initial_call=True
)
def get_allocate_user_table_data(search_click, refresh_click, pagination, operations, user_name, phonenumber, role_id, button_perms):
+ """
+ 使用模式匹配回调MATCH模式,根据不同类型获取角色已分配用户列表及未分配用户列表(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
role_id=int(role_id),
@@ -76,9 +80,10 @@ def get_allocate_user_table_data(search_click, refresh_click, pagination, operat
return [dash.no_update, dash.no_update, dash.no_update, dash.no_update]
- return [dash.no_update] * 4
+ raise PreventUpdate
+# 重置分配用户搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -96,6 +101,7 @@ app.clientside_callback(
)
+# 隐藏/显示分配用户搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -122,6 +128,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_allocated_user_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制取批量消授权按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -129,7 +138,7 @@ def change_allocated_user_delete_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -140,11 +149,14 @@ def change_allocated_user_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def allocate_user_modal(add_click, unallocated_user):
+ """
+ 分配用户弹框中添加用户按钮回调
+ """
if add_click:
return [True, unallocated_user + 1 if unallocated_user else 1]
- return [dash.no_update] * 2
+ raise PreventUpdate
@app.callback(
@@ -158,6 +170,9 @@ def allocate_user_modal(add_click, unallocated_user):
prevent_initial_call=True
)
def allocate_user_add_confirm(add_confirm, selected_row_keys, role_id):
+ """
+ 添加用户确认回调,实现给角色分配用户操作
+ """
if add_confirm:
if selected_row_keys:
@@ -185,7 +200,7 @@ def allocate_user_add_confirm(add_confirm, selected_row_keys, role_id):
fuc.FefferyFancyMessage('请选择用户', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -201,6 +216,9 @@ def allocate_user_add_confirm(add_confirm, selected_row_keys, role_id):
)
def allocate_user_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示取消授权二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.type == 'allocate_user-operation-button' or (
trigger_id.type == 'allocate_user-list-table' and clicked_content == '取消授权'):
@@ -219,7 +237,7 @@ def allocate_user_delete_modal(operation_click, button_click,
user_ids
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -232,6 +250,9 @@ def allocate_user_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def allocate_user_delete_confirm(delete_confirm, user_ids_data, role_id):
+ """
+ 取消授权弹窗确认回调,实现取消授权操作
+ """
if delete_confirm:
params = {'user_ids': user_ids_data, 'role_ids': role_id}
@@ -249,4 +270,4 @@ def allocate_user_delete_confirm(delete_confirm, user_ids_data, role_id):
fuc.FefferyFancyMessage('取消授权失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/role_c/role_c.py b/dash-fastapi-frontend/callbacks/system_c/role_c/role_c.py
index b419d9bf709ce0a3d01d2ac9639a532b7f04687d..de81624abc17d278a0a7dd567b1ec3644c0d9ada 100644
--- a/dash-fastapi-frontend/callbacks/system_c/role_c/role_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/role_c/role_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_antd_components as fac
import feffery_utils_components as fuc
@@ -12,23 +13,32 @@ from api.menu import get_menu_tree_api
@app.callback(
- [Output('role-list-table', 'data', allow_duplicate=True),
- Output('role-list-table', 'pagination', allow_duplicate=True),
- Output('role-list-table', 'key'),
- Output('role-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('role-search', 'nClicks'),
- Input('role-refresh', 'nClicks'),
- Input('role-list-table', 'pagination'),
- Input('role-operations-store', 'data')],
- [State('role-role_name-input', 'value'),
- State('role-role_key-input', 'value'),
- State('role-status-select', 'value'),
- State('role-create_time-range', 'value'),
- State('role-button-perms-container', 'data')],
+ output=dict(
+ role_table_data=Output('role-list-table', 'data', allow_duplicate=True),
+ role_table_pagination=Output('role-list-table', 'pagination', allow_duplicate=True),
+ role_table_key=Output('role-list-table', 'key'),
+ role_table_selectedrowkeys=Output('role-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ search_click=Input('role-search', 'nClicks'),
+ refresh_click=Input('role-refresh', 'nClicks'),
+ pagination=Input('role-list-table', 'pagination'),
+ operations=Input('role-operations-store', 'data')
+ ),
+ state=dict(
+ role_name=State('role-role_name-input', 'value'),
+ role_key=State('role-role_key-input', 'value'),
+ status_select=State('role-status-select', 'value'),
+ create_time_range=State('role-create_time-range', 'value'),
+ button_perms=State('role-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_role_table_data(search_click, refresh_click, pagination, operations, role_name, role_key, status_select, create_time_range, button_perms):
+ """
+ 获取角色表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
create_time_start = None
create_time_end = None
@@ -69,9 +79,9 @@ def get_role_table_data(search_click, refresh_click, pagination, operations, rol
)
for item in table_data:
if item['status'] == '0':
- item['status'] = dict(checked=True)
+ item['status'] = dict(checked=True, disabled=item['role_id'] == 1)
else:
- item['status'] = dict(checked=False)
+ item['status'] = dict(checked=False, disabled=item['role_id'] == 1)
item['key'] = str(item['role_id'])
if item['role_id'] == 1:
item['operation'] = []
@@ -161,13 +171,26 @@ def get_role_table_data(search_click, refresh_click, pagination, operations, rol
]
)
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ role_table_data=table_data,
+ role_table_pagination=table_pagination,
+ role_table_key=str(uuid.uuid4()),
+ role_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ role_table_data=dash.no_update,
+ role_table_pagination=dash.no_update,
+ role_table_key=dash.no_update,
+ role_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置角色搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -187,6 +210,7 @@ app.clientside_callback(
)
+# 隐藏/显示角色搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -213,6 +237,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_role_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -232,13 +259,14 @@ def change_role_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_role_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
if '1' in table_rows_selected:
return True
- if len(table_rows_selected) > 1:
- return False
return False
@@ -254,6 +282,9 @@ def change_role_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def fold_unfold_role_menu(fold_unfold, menu_info):
+ """
+ 新增和编辑表单中展开/折叠checkbox回调
+ """
if menu_info:
default_expanded_keys = []
for item in menu_info:
@@ -275,6 +306,9 @@ def fold_unfold_role_menu(fold_unfold, menu_info):
prevent_initial_call=True
)
def all_none_role_menu_mode(all_none, menu_info):
+ """
+ 新增和编辑表单中全选/全不选checkbox回调
+ """
if menu_info:
default_expanded_keys = []
for item in menu_info:
@@ -297,6 +331,9 @@ def all_none_role_menu_mode(all_none, menu_info):
prevent_initial_call=True
)
def change_role_menu_mode(parent_children, current_role_menu):
+ """
+ 新增和编辑表单中父子联动checkbox回调
+ """
checked_menu = []
if parent_children:
if current_role_menu:
@@ -316,53 +353,63 @@ def change_role_menu_mode(parent_children, current_role_menu):
@app.callback(
- [Output('role-modal', 'visible', allow_duplicate=True),
- Output('role-modal', 'title'),
- Output('role-role_name', 'value'),
- Output('role-role_key', 'value'),
- Output('role-role_sort', 'value'),
- Output('role-status', 'value'),
- Output('role-menu-perms', 'treeData'),
- Output('role-menu-perms', 'expandedKeys', allow_duplicate=True),
- Output('role-menu-perms', 'checkedKeys', allow_duplicate=True),
- Output('role-menu-perms', 'halfCheckedKeys', allow_duplicate=True),
- Output('role-menu-store', 'data'),
- Output('current-role-menu-store', 'data'),
- Output('role-remark', 'value'),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('role-edit-id-store', 'data'),
- Output('role-operations-store-bk', 'data')],
- [Input({'type': 'role-operation-button', 'operation': ALL}, 'nClicks'),
- Input({'type': 'role-operation-table', 'operation': ALL, 'index': ALL}, 'nClicks')],
- State('role-list-table', 'selectedRowKeys'),
+ output=dict(
+ modal_visible=Output('role-modal', 'visible', allow_duplicate=True),
+ modal_title=Output('role-modal', 'title'),
+ form_value=Output({'type': 'role-form-value', 'index': ALL, 'required': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'role-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'role-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ menu_perms_tree=Output('role-menu-perms', 'treeData'),
+ menu_perms_expandedkeys=Output('role-menu-perms', 'expandedKeys', allow_duplicate=True),
+ menu_perms_checkedkeys=Output('role-menu-perms', 'checkedKeys', allow_duplicate=True),
+ menu_perms_halfcheckedkeys=Output('role-menu-perms', 'halfCheckedKeys', allow_duplicate=True),
+ role_menu=Output('role-menu-store', 'data'),
+ current_role_menu=Output('current-role-menu-store', 'data'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ edit_row_info=Output('role-edit-id-store', 'data'),
+ modal_type=Output('role-operations-store-bk', 'data')
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'role-operation-button', 'operation': ALL}, 'nClicks'),
+ button_click=Input({'type': 'role-operation-table', 'operation': ALL, 'index': ALL}, 'nClicks')
+ ),
+ state=dict(
+ selected_row_keys=State('role-list-table', 'selectedRowKeys')
+ ),
prevent_initial_call=True
)
def add_edit_role_modal(operation_click, button_click, selected_row_keys):
+ """
+ 显示新增或编辑角色弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.operation in ['add', 'edit']:
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
menu_params = dict(menu_name='', type='role')
tree_info = get_menu_tree_api(menu_params)
if tree_info.get('code') == 200:
tree_data = tree_info['data']
if trigger_id.type == 'role-operation-button' and trigger_id.operation == 'add':
- return [
- True,
- '新增角色',
- None,
- None,
- None,
- '0',
- tree_data[0],
- [],
- None,
- None,
- tree_data[1],
- None,
- None,
- {'timestamp': time.time()},
- None,
- {'type': 'add'}
- ]
+ role_info = dict(role_name=None, role_key=None, role_sort=None, status='0', remark=None)
+ return dict(
+ modal_visible=True,
+ modal_title='新增角色',
+ form_value=[role_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ menu_perms_tree=tree_data[0],
+ menu_perms_expandedkeys=[],
+ menu_perms_checkedkeys=None,
+ menu_perms_halfcheckedkeys=None,
+ role_menu=tree_data[1],
+ current_role_menu=None,
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type={'type': 'add'}
+ )
elif trigger_id.operation == 'edit':
if trigger_id.type == 'role-operation-button':
role_id = int(','.join(selected_row_keys))
@@ -384,125 +431,134 @@ def add_edit_role_modal(operation_click, button_click, selected_row_keys):
if not has_children:
checked_menu.append(str(item.get('menu_id')))
half_checked_menu = [x for x in checked_menu_all if x not in checked_menu]
- return [
- True,
- '编辑角色',
- role_info.get('role').get('role_name'),
- role_info.get('role').get('role_key'),
- role_info.get('role').get('role_sort'),
- role_info.get('role').get('status'),
- tree_data[0],
- [],
- checked_menu,
- half_checked_menu,
- tree_data[1],
- role_info.get('menu'),
- role_info.get('role').get('remark'),
- {'timestamp': time.time()},
- role_info.get('role') if role_info else None,
- {'type': 'edit'}
- ]
-
- return [dash.no_update] * 13 + [{'timestamp': time.time()}, None, None]
-
- return [dash.no_update] * 14 + [None, None]
+ return dict(
+ modal_visible=True,
+ modal_title='编辑角色',
+ form_value=[role_info.get('role').get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ menu_perms_tree=tree_data[0],
+ menu_perms_expandedkeys=[],
+ menu_perms_checkedkeys=checked_menu,
+ menu_perms_halfcheckedkeys=half_checked_menu,
+ role_menu=tree_data[1],
+ current_role_menu=role_info.get('menu'),
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=role_info.get('role') if role_info else None,
+ modal_type={'type': 'edit'}
+ )
+
+ return dict(
+ modal_visible=dash.no_update,
+ modal_title=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_value_list),
+ form_label_validate_info=[dash.no_update] * len(form_value_list),
+ menu_perms_tree=dash.no_update,
+ menu_perms_expandedkeys=dash.no_update,
+ menu_perms_checkedkeys=dash.no_update,
+ menu_perms_halfcheckedkeys=dash.no_update,
+ role_menu=dash.no_update,
+ current_role_menu=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ edit_row_info=None,
+ modal_type=None
+ )
+
+ raise PreventUpdate
@app.callback(
- [Output('role-role_name-form-item', 'validateStatus'),
- Output('role-role_Key-form-item', 'validateStatus'),
- Output('role-role_sort-form-item', 'validateStatus'),
- Output('role-role_name-form-item', 'help'),
- Output('role-role_Key-form-item', 'help'),
- Output('role-role_sort-form-item', 'help'),
- Output('role-modal', 'visible'),
- Output('role-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('role-modal', 'okCounts'),
- [State('role-operations-store-bk', 'data'),
- State('role-edit-id-store', 'data'),
- State('role-role_name', 'value'),
- State('role-role_key', 'value'),
- State('role-role_sort', 'value'),
- State('role-status', 'value'),
- State('role-menu-perms', 'checkedKeys'),
- State('role-menu-perms', 'halfCheckedKeys'),
- State('role-menu-perms-radio-parent-children', 'checked'),
- State('role-remark', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'role-form-label', 'index': ALL, 'required': True}, 'validateStatus',
+ allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'role-form-label', 'index': ALL, 'required': True}, 'help',
+ allow_duplicate=True),
+ modal_visible=Output('role-modal', 'visible'),
+ operations=Output('role-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ confirm_trigger=Input('role-modal', 'okCounts')
+ ),
+ state=dict(
+ modal_type=State('role-operations-store-bk', 'data'),
+ edit_row_info=State('role-edit-id-store', 'data'),
+ form_value=State({'type': 'role-form-value', 'index': ALL, 'required': ALL}, 'value'),
+ form_label=State({'type': 'role-form-value', 'index': ALL, 'required': True}, 'placeholder'),
+ menu_checked_keys=State('role-menu-perms', 'checkedKeys'),
+ menu_half_checked_keys=State('role-menu-perms', 'halfCheckedKeys'),
+ parent_checked=State('role-menu-perms-radio-parent-children', 'checked')
+ ),
prevent_initial_call=True
)
-def role_confirm(confirm_trigger, operation_type, cur_role_info, role_name, role_key, role_sort, status, menu_checked_keys, menu_half_checked_keys, parent_checked, remark):
+def role_confirm(confirm_trigger, modal_type, edit_row_info, form_value, form_label, menu_checked_keys, menu_half_checked_keys, parent_checked):
+ """
+ 新增或编辑角色弹窗确认回调,实现新增或编辑操作
+ """
if confirm_trigger:
- if all([role_name, role_key, role_sort]):
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[3]}
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ menu_half_checked_keys = menu_half_checked_keys if menu_half_checked_keys else []
+ menu_checked_keys = menu_checked_keys if menu_checked_keys else []
if parent_checked:
menu_perms = menu_half_checked_keys + menu_checked_keys
else:
menu_perms = menu_checked_keys
- params_add = dict(role_name=role_name, role_key=role_key, role_sort=role_sort, menu_id=','.join(menu_perms) if menu_perms else None, status=status, remark=remark)
- params_edit = dict(role_id=cur_role_info.get('role_id') if cur_role_info else None, role_name=role_name, role_key=role_key, role_sort=role_sort,
- menu_id=','.join(menu_perms) if menu_perms else '', status=status, remark=remark)
+ params_add = form_value_state
+ params_add['menu_id'] = ','.join(menu_perms) if menu_perms else None
+ params_edit = params_add.copy()
+ params_edit['role_id'] = edit_row_info.get('role_id') if edit_row_info else None
api_res = {}
- operation_type = operation_type.get('type')
- if operation_type == 'add':
+ modal_type = modal_type.get('type')
+ if modal_type == 'add':
api_res = add_role_api(params_add)
- if operation_type == 'edit':
+ if modal_type == 'edit':
api_res = edit_role_api(params_edit)
if api_res.get('code') == 200:
- if operation_type == 'add':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
- if operation_type == 'edit':
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
-
- return [
- None if role_name else 'error',
- None if role_key else 'error',
- None if role_sort else 'error',
- None if role_name else '请输入角色名称!',
- None if role_key else '请输入权限字符!',
- None if role_sort else '请输入角色排序!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('处理失败', type='error')
- ]
+ if modal_type == 'add':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+ if modal_type == 'edit':
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
- return [dash.no_update] * 10
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else form_label_state.get(k) for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('处理失败', type='error')
+ )
+
+ raise PreventUpdate
@app.callback(
@@ -515,6 +571,9 @@ def role_confirm(confirm_trigger, operation_type, cur_role_info, role_name, role
prevent_initial_call=True
)
def table_switch_role_status(recently_switch_data_index, recently_switch_status, recently_switch_row):
+ """
+ 表格内切换角色状态回调
+ """
if recently_switch_data_index:
if recently_switch_status:
params = dict(role_id=int(recently_switch_row['key']), status='0', type='status')
@@ -530,12 +589,12 @@ def table_switch_role_status(recently_switch_data_index, recently_switch_status,
]
return [
- dash.no_update,
+ {'type': 'switch-status'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('修改失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -548,6 +607,9 @@ def table_switch_role_status(recently_switch_data_index, recently_switch_status,
prevent_initial_call=True
)
def role_delete_modal(operation_click, button_click, selected_row_keys):
+ """
+ 显示删除角色二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.operation == 'delete':
@@ -557,7 +619,7 @@ def role_delete_modal(operation_click, button_click, selected_row_keys):
if trigger_id.type == 'role-operation-table':
role_ids = trigger_id.index
else:
- return dash.no_update
+ raise PreventUpdate
return [
f'是否确认删除角色编号为{role_ids}的角色?',
@@ -565,7 +627,7 @@ def role_delete_modal(operation_click, button_click, selected_row_keys):
{'role_ids': role_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -577,6 +639,9 @@ def role_delete_modal(operation_click, button_click, selected_row_keys):
prevent_initial_call=True
)
def role_delete_confirm(delete_confirm, role_ids_data):
+ """
+ 删除角色弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = role_ids_data
@@ -594,7 +659,7 @@ def role_delete_confirm(delete_confirm, role_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -606,6 +671,9 @@ def role_delete_confirm(delete_confirm, role_ids_data):
prevent_initial_call=True
)
def role_to_allocated_user_modal(allocated_click, allocated_user_search_nclick):
+ """
+ 显示角色分配用户弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.operation == 'allocation':
return [
@@ -614,7 +682,7 @@ def role_to_allocated_user_modal(allocated_click, allocated_user_search_nclick):
trigger_id.index
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -626,6 +694,9 @@ def role_to_allocated_user_modal(allocated_click, allocated_user_search_nclick):
prevent_initial_call=True
)
def export_role_list(export_click):
+ """
+ 导出角色信息回调
+ """
if export_click:
export_role_res = export_role_list_api({})
if export_role_res.status_code == 200:
@@ -645,7 +716,7 @@ def export_role_list(export_click):
fuc.FefferyFancyMessage('导出失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -654,22 +725,12 @@ def export_role_list(export_click):
prevent_initial_call=True
)
def reset_role_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
-
-
-# 由于采用了自定义单元格元素,路由变化时需要重置selectedRows,不然会报错
-app.clientside_callback(
- '''
- (url) => {
- return null;
- }
- ''',
- Output('role-list-table', 'selectedRows'),
- Input('url-container', 'pathname'),
- prevent_initial_call=True
-)
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/user_c/allocate_role_c.py b/dash-fastapi-frontend/callbacks/system_c/user_c/allocate_role_c.py
index a62052b449b83f80f40fcb07d26134e32fd297f0..5ddf787de2774f834e147a43961116a4691607b7 100644
--- a/dash-fastapi-frontend/callbacks/system_c/user_c/allocate_role_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/user_c/allocate_role_c.py
@@ -2,6 +2,7 @@ import dash
import time
import uuid
from dash.dependencies import Input, Output, State, ALL, MATCH
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -24,6 +25,9 @@ from api.user import get_allocated_role_list_api, get_unallocated_role_list_api,
prevent_initial_call=True
)
def get_allocate_role_table_data(search_click, refresh_click, pagination, operations, role_name, role_key, user_id, button_perms):
+ """
+ 使用模式匹配回调MATCH模式,根据不同类型获取用户已分配角色列表及未分配角色列表(进行表格相关增删查改操作后均会触发此回调)
+ """
query_params = dict(
user_id=int(user_id),
@@ -76,9 +80,10 @@ def get_allocate_role_table_data(search_click, refresh_click, pagination, operat
return [dash.no_update, dash.no_update, dash.no_update, dash.no_update]
- return [dash.no_update] * 4
+ raise PreventUpdate
+# 重置分配角色搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -96,6 +101,7 @@ app.clientside_callback(
)
+# 隐藏/显示分配角色搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -122,6 +128,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_allocated_role_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制取批量消授权按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -129,7 +138,7 @@ def change_allocated_role_delete_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -140,11 +149,14 @@ def change_allocated_role_delete_button_status(table_rows_selected):
prevent_initial_call=True
)
def allocate_role_modal(add_click, unallocated_role):
+ """
+ 分配角色弹框中添加角色按钮回调
+ """
if add_click:
return [True, unallocated_role + 1 if unallocated_role else 1]
- return [dash.no_update] * 2
+ raise PreventUpdate
@app.callback(
@@ -158,6 +170,9 @@ def allocate_role_modal(add_click, unallocated_role):
prevent_initial_call=True
)
def allocate_user_add_confirm(add_confirm, selected_row_keys, user_id):
+ """
+ 添加角色确认回调,实现给用户分配角色操作
+ """
if add_confirm:
if selected_row_keys:
@@ -185,7 +200,7 @@ def allocate_user_add_confirm(add_confirm, selected_row_keys, user_id):
fuc.FefferyFancyMessage('请选择角色', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -201,6 +216,9 @@ def allocate_user_add_confirm(add_confirm, selected_row_keys, user_id):
)
def allocate_role_delete_modal(operation_click, button_click,
selected_row_keys, clicked_content, recently_button_clicked_row):
+ """
+ 显示取消授权二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id.type == 'allocate_role-operation-button' or (
trigger_id.type == 'allocate_role-list-table' and clicked_content == '取消授权'):
@@ -219,7 +237,7 @@ def allocate_role_delete_modal(operation_click, button_click,
role_ids
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -232,6 +250,9 @@ def allocate_role_delete_modal(operation_click, button_click,
prevent_initial_call=True
)
def allocate_role_delete_confirm(delete_confirm, role_ids_data, user_id):
+ """
+ 取消授权弹窗确认回调,实现取消授权操作
+ """
if delete_confirm:
params = {'user_ids': user_id, 'role_ids': role_ids_data}
@@ -249,4 +270,4 @@ def allocate_role_delete_confirm(delete_confirm, role_ids_data, user_id):
fuc.FefferyFancyMessage('取消授权失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/avatar_c.py b/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/avatar_c.py
index 1e2cb444f9b8e352d17f2bd06351c093c3e2e85e..0930ec4d33752d37166ed368f39549ccc6a2f5f1 100644
--- a/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/avatar_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/avatar_c.py
@@ -3,6 +3,7 @@ import feffery_utils_components as fuc
import time
import uuid
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
from server import app
from api.user import change_user_avatar_api
@@ -16,10 +17,13 @@ from api.user import change_user_avatar_api
prevent_initial_call=True
)
def avatar_cropper_modal_visible(n_clicks, user_avatar_image_info):
+ """
+ 显示编辑头像弹窗回调
+ """
if n_clicks:
return [True, user_avatar_image_info]
- return dash.no_update, dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -28,11 +32,14 @@ def avatar_cropper_modal_visible(n_clicks, user_avatar_image_info):
prevent_initial_call=True
)
def upload_user_avatar(list_upload_task_record):
+ """
+ 上传用户头像获取后端url回调
+ """
if list_upload_task_record:
return list_upload_task_record[-1].get('url')
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -41,6 +48,9 @@ def upload_user_avatar(list_upload_task_record):
prevent_initial_call=True
)
def edit_user_avatar(src_data):
+ """
+ 使用cropper.js编辑头像回调
+ """
return """
// 创建新图像元素
@@ -127,6 +137,9 @@ def edit_user_avatar(src_data):
prevent_initial_call=True
)
def change_user_avatar_callback(submit_click, avatar_data):
+ """
+ 提交编辑完成头像数据回调,实现更新头像操作
+ """
if submit_click:
params = dict(type='avatar', avatar=avatar_data['avatarBase64'])
@@ -149,4 +162,4 @@ def change_user_avatar_callback(submit_click, avatar_data):
dash.no_update
]
- return [dash.no_update] * 5
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/reset_pwd_c.py b/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/reset_pwd_c.py
index a5457d83e164dcd6b0aeece010398c8c3763c85b..ca81b66d2d2b6645e9f4b2e288e4204e5a109580 100644
--- a/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/reset_pwd_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/reset_pwd_c.py
@@ -2,6 +2,7 @@ import dash
import feffery_utils_components as fuc
import time
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
from server import app
from api.user import reset_user_password_api
@@ -23,6 +24,9 @@ from api.user import reset_user_password_api
prevent_initial_call=True
)
def reset_submit_user_info(reset_click, old_password, new_password, confirm_password):
+ """
+ 重置当前用户密码回调
+ """
if reset_click:
if all([old_password, new_password, confirm_password]):
@@ -76,7 +80,7 @@ def reset_submit_user_info(reset_click, old_password, new_password, confirm_pass
fuc.FefferyFancyMessage('修改失败', type='error'),
]
- return [dash.no_update] * 8
+ raise PreventUpdate
@app.callback(
@@ -85,7 +89,10 @@ def reset_submit_user_info(reset_click, old_password, new_password, confirm_pass
prevent_initial_call=True
)
def close_personal_info_modal(close_click):
+ """
+ 关闭当前个人资料标签页回调
+ """
if close_click:
return '个人资料'
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/user_info_c.py b/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/user_info_c.py
index 6cdef31d617d3359dcf0d5ccc54bc3dcdf39fa25..6b2769d84537e601a4ecdaf328386f562195a5f9 100644
--- a/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/user_info_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/user_c/profile_c/user_info_c.py
@@ -2,6 +2,7 @@ import dash
import feffery_utils_components as fuc
import time
from dash.dependencies import Input, Output, State
+from dash.exceptions import PreventUpdate
from server import app
from api.user import change_user_info_api
@@ -24,6 +25,9 @@ from api.user import change_user_info_api
prevent_initial_call=True
)
def reset_submit_user_info(reset_click, nick_name, phonenumber, email, sex):
+ """
+ 修改当前用户信息回调
+ """
if reset_click:
if all([nick_name, phonenumber, email]):
@@ -64,7 +68,7 @@ def reset_submit_user_info(reset_click, nick_name, phonenumber, email, sex):
fuc.FefferyFancyMessage('修改失败', type='error'),
]
- return [dash.no_update] * 8
+ raise PreventUpdate
@app.callback(
@@ -73,7 +77,10 @@ def reset_submit_user_info(reset_click, nick_name, phonenumber, email, sex):
prevent_initial_call=True
)
def close_personal_info_modal(close_click):
+ """
+ 关闭当前个人资料标签页回调
+ """
if close_click:
return '个人资料'
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/callbacks/system_c/user_c/user_c.py b/dash-fastapi-frontend/callbacks/system_c/user_c/user_c.py
index 9e3ebbcd6a820f7185e2783325a4796204c34fa8..b5c03cc00c685ca4931f429714bb064a3a57c6b0 100644
--- a/dash-fastapi-frontend/callbacks/system_c/user_c/user_c.py
+++ b/dash-fastapi-frontend/callbacks/system_c/user_c/user_c.py
@@ -3,6 +3,7 @@ import time
import uuid
from dash import dcc
from dash.dependencies import Input, Output, State, ALL
+from dash.exceptions import PreventUpdate
import feffery_utils_components as fuc
from server import app
@@ -30,25 +31,34 @@ def get_search_dept_tree(dept_input):
@app.callback(
- [Output('user-list-table', 'data', allow_duplicate=True),
- Output('user-list-table', 'pagination', allow_duplicate=True),
- Output('user-list-table', 'key'),
- Output('user-list-table', 'selectedRowKeys'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input('dept-tree', 'selectedKeys'),
- Input('user-search', 'nClicks'),
- Input('user-refresh', 'nClicks'),
- Input('user-list-table', 'pagination'),
- Input('user-operations-store', 'data')],
- [State('user-user_name-input', 'value'),
- State('user-phone_number-input', 'value'),
- State('user-status-select', 'value'),
- State('user-create_time-range', 'value'),
- State('user-button-perms-container', 'data')],
+ output=dict(
+ user_table_data=Output('user-list-table', 'data', allow_duplicate=True),
+ user_table_pagination=Output('user-list-table', 'pagination', allow_duplicate=True),
+ user_table_key=Output('user-list-table', 'key'),
+ user_table_selectedrowkeys=Output('user-list-table', 'selectedRowKeys'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ selected_dept_tree=Input('dept-tree', 'selectedKeys'),
+ search_click=Input('user-search', 'nClicks'),
+ refresh_click=Input('user-refresh', 'nClicks'),
+ pagination=Input('user-list-table', 'pagination'),
+ operations=Input('user-operations-store', 'data')
+ ),
+ state=dict(
+ user_name=State('user-user_name-input', 'value'),
+ phone_number=State('user-phone_number-input', 'value'),
+ status_select=State('user-status-select', 'value'),
+ create_time_range=State('user-create_time-range', 'value'),
+ button_perms=State('user-button-perms-container', 'data')
+ ),
prevent_initial_call=True
)
def get_user_table_data_by_dept_tree(selected_dept_tree, search_click, refresh_click, pagination, operations,
user_name, phone_number, status_select, create_time_range, button_perms):
+ """
+ 获取用户表格数据回调(进行表格相关增删查改操作后均会触发此回调)
+ """
dept_id = None
create_time_start = None
create_time_end = None
@@ -119,13 +129,26 @@ def get_user_table_data_by_dept_tree(selected_dept_tree, search_click, refresh_c
} if 'system:user:edit' in button_perms else None
]
- return [table_data, table_pagination, str(uuid.uuid4()), None, {'timestamp': time.time()}]
+ return dict(
+ user_table_data=table_data,
+ user_table_pagination=table_pagination,
+ user_table_key=str(uuid.uuid4()),
+ user_table_selectedrowkeys=None,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update, dash.no_update, dash.no_update, dash.no_update, {'timestamp': time.time()}]
+ return dict(
+ user_table_data=dash.no_update,
+ user_table_pagination=dash.no_update,
+ user_table_key=dash.no_update,
+ user_table_selectedrowkeys=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
+# 重置用户搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
@@ -146,6 +169,7 @@ app.clientside_callback(
)
+# 隐藏/显示用户搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
@@ -172,6 +196,9 @@ app.clientside_callback(
prevent_initial_call=True
)
def change_user_edit_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制编辑按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
@@ -182,7 +209,7 @@ def change_user_edit_button_status(table_rows_selected):
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
@@ -191,32 +218,49 @@ def change_user_edit_button_status(table_rows_selected):
prevent_initial_call=True
)
def change_user_delete_button_status(table_rows_selected):
+ """
+ 根据选择的表格数据行数控制删除按钮状态回调
+ """
outputs_list = dash.ctx.outputs_list
if outputs_list:
if table_rows_selected:
if '1' in table_rows_selected:
return True
- if len(table_rows_selected) > 1:
- return False
return False
return True
- return dash.no_update
+ raise PreventUpdate
@app.callback(
- [Output('user-add-modal', 'visible', allow_duplicate=True),
- Output('user-add-dept_id', 'treeData'),
- Output('user-add-post', 'options'),
- Output('user-add-role', 'options'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- Input('user-add', 'nClicks'),
+ output=dict(
+ modal_visible=Output('user-add-modal', 'visible', allow_duplicate=True),
+ dept_tree=Output({'type': 'user_add-form-value', 'index': 'dept_id'}, 'treeData'),
+ form_value=Output({'type': 'user_add-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'user_add-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'user_add-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ user_post=Output('user-add-post', 'value'),
+ user_role=Output('user-add-role', 'value'),
+ post_option=Output('user-add-post', 'options'),
+ role_option=Output('user-add-role', 'options'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ add_click=Input('user-add', 'nClicks')
+ ),
prevent_initial_call=True
)
def add_user_modal(add_click):
+ """
+ 显示新增用户弹窗回调
+ """
if add_click:
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
dept_params = dict(dept_name='')
tree_info = get_dept_tree_api(dept_params)
post_option_info = get_post_select_option_api()
@@ -225,126 +269,138 @@ def add_user_modal(add_click):
tree_data = tree_info['data']
post_option = post_option_info['data']
role_option = role_option_info['data']
+ user_info = dict(nick_name=None, dept_id=None, phonenumber=None, email=None, user_name=None, password=None, sex=None, status='0', remark=None)
+
+ return dict(
+ modal_visible=True,
+ dept_tree=tree_data,
+ form_value=[user_info.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ user_post=None,
+ user_role=None,
+ post_option=[dict(label=item['post_name'], value=item['post_id']) for item in post_option],
+ role_option=[dict(label=item['role_name'], value=item['role_id']) for item in role_option],
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [
- True,
- tree_data,
- [dict(label=item['post_name'], value=item['post_id']) for item in post_option],
- [dict(label=item['role_name'], value=item['role_id']) for item in role_option],
- {'timestamp': time.time()}
- ]
-
- return [dash.no_update] * 4 + [{'timestamp': time.time()}]
+ return dict(
+ modal_visible=dash.no_update,
+ dept_tree=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ user_post=dash.no_update,
+ user_role=dash.no_update,
+ post_option=dash.no_update,
+ role_option=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 5
+ raise PreventUpdate
@app.callback(
- [Output('user-add-nick_name-form-item', 'validateStatus'),
- Output('user-add-user_name-form-item', 'validateStatus'),
- Output('user-add-password-form-item', 'validateStatus'),
- Output('user-add-nick_name-form-item', 'help'),
- Output('user-add-user_name-form-item', 'help'),
- Output('user-add-password-form-item', 'help'),
- Output('user-add-modal', 'visible', allow_duplicate=True),
- Output('user-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('user-add-modal', 'okCounts'),
- [State('user-add-nick_name', 'value'),
- State('user-add-dept_id', 'value'),
- State('user-add-phone_number', 'value'),
- State('user-add-email', 'value'),
- State('user-add-user_name', 'value'),
- State('user-add-password', 'value'),
- State('user-add-sex', 'value'),
- State('user-add-status', 'value'),
- State('user-add-post', 'value'),
- State('user-add-role', 'value'),
- State('user-add-remark', 'value')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'user_add-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'user_add-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ modal_visible=Output('user-add-modal', 'visible', allow_duplicate=True),
+ operations=Output('user-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ add_confirm=Input('user-add-modal', 'okCounts')
+ ),
+ state=dict(
+ post=State('user-add-post', 'value'),
+ role=State('user-add-role', 'value'),
+ form_value=State({'type': 'user_add-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'user_add-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def usr_add_confirm(add_confirm, nick_name, dept_id, phone_number, email, user_name, password, sex, status, post, role,
- remark):
+def usr_add_confirm(add_confirm, post, role, form_value, form_label):
if add_confirm:
-
- if all([nick_name, user_name, password]):
- params = dict(nick_name=nick_name, dept_id=dept_id, phonenumber=phone_number,
- email=email, user_name=user_name, password=password, sex=sex,
- status=status, post_id=','.join(map(str, post)) if post else '',
- role_id=','.join(map(str, role)) if role else '', remark=remark)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params = form_value_state
+ params['post_id'] = ','.join(map(str, post)) if post else ''
+ params['role_id'] = ','.join(map(str, role)) if role else ''
add_button_result = add_user_api(params)
if add_button_result['code'] == 200:
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- False,
- {'type': 'add'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增成功', type='success')
- ]
-
- return [
- None,
- None,
- None,
- None,
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'add'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增失败', type='error')
+ )
- return [
- None if nick_name else 'error',
- None if user_name else 'error',
- None if password else 'error',
- None if nick_name else '请输入用户昵称!',
- None if user_name else '请输入用户名称!',
- None if password else '请输入用户密码!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('新增失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('新增失败', type='error')
+ )
- return [dash.no_update] * 10
+ raise PreventUpdate
@app.callback(
- [Output('user-edit-modal', 'visible', allow_duplicate=True),
- Output('user-edit-dept_id', 'treeData'),
- Output('user-edit-post', 'options'),
- Output('user-edit-role', 'options'),
- Output('user-edit-nick_name', 'value'),
- Output('user-edit-dept_id', 'value'),
- Output('user-edit-phone_number', 'value'),
- Output('user-edit-email', 'value'),
- Output('user-edit-sex', 'value'),
- Output('user-edit-status', 'value'),
- Output('user-edit-post', 'value'),
- Output('user-edit-role', 'value'),
- Output('user-edit-remark', 'value'),
- Output('user-edit-id-store', 'data'),
- Output('api-check-token', 'data', allow_duplicate=True)],
- [Input({'type': 'user-operation-button', 'index': ALL}, 'nClicks'),
- Input('user-list-table', 'nClicksDropdownItem')],
- [State('user-list-table', 'selectedRowKeys'),
- State('user-list-table', 'recentlyClickedDropdownItemTitle'),
- State('user-list-table', 'recentlyDropdownItemClickedRow')],
+ output=dict(
+ modal_visible=Output('user-edit-modal', 'visible', allow_duplicate=True),
+ dept_tree=Output({'type': 'user_edit-form-value', 'index': 'dept_id'}, 'treeData'),
+ form_value=Output({'type': 'user_edit-form-value', 'index': ALL}, 'value'),
+ form_label_validate_status=Output({'type': 'user_edit-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'user_edit-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ user_post=Output('user-edit-post', 'value'),
+ user_role=Output('user-edit-role', 'value'),
+ post_option=Output('user-edit-post', 'options'),
+ role_option=Output('user-edit-role', 'options'),
+ edit_row_info=Output('user-edit-id-store', 'data'),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True)
+ ),
+ inputs=dict(
+ operation_click=Input({'type': 'user-operation-button', 'index': ALL}, 'nClicks'),
+ dropdown_click=Input('user-list-table', 'nClicksDropdownItem')
+ ),
+ state=dict(
+ selected_row_keys=State('user-list-table', 'selectedRowKeys'),
+ recently_clicked_dropdown_item_title=State('user-list-table', 'recentlyClickedDropdownItemTitle'),
+ recently_dropdown_item_clicked_row=State('user-list-table', 'recentlyDropdownItemClickedRow')
+ ),
prevent_initial_call=True
)
def user_edit_modal(operation_click, dropdown_click,
selected_row_keys, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row):
+ """
+ 显示编辑用户弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'edit', 'type': 'user-operation-button'} or (trigger_id == 'user-list-table' and recently_clicked_dropdown_item_title == '修改'):
+ # 获取所有输出表单项对应value的index
+ form_value_list = [x['id']['index'] for x in dash.ctx.outputs_list[2]]
+ # 获取所有输出表单项对应label的index
+ form_label_list = [x['id']['index'] for x in dash.ctx.outputs_list[3]]
dept_params = dict(dept_name='')
tree_data = get_dept_tree_api(dept_params)['data']
@@ -357,97 +413,111 @@ def user_edit_modal(operation_click, dropdown_click,
if recently_clicked_dropdown_item_title == '修改':
user_id = int(recently_dropdown_item_clicked_row['key'])
else:
- return [dash.no_update] * 15
+ raise PreventUpdate
edit_button_info = get_user_detail_api(user_id)
if edit_button_info['code'] == 200:
edit_button_result = edit_button_info['data']
user = edit_button_result['user']
- dept = edit_button_result['dept']
role = edit_button_result['role']
post = edit_button_result['post']
- return [
- True,
- tree_data,
- [dict(label=item['post_name'], value=item['post_id']) for item in post_option if item] or [],
- [dict(label=item['role_name'], value=item['role_id']) for item in role_option if item] or [],
- user['nick_name'],
- dept['dept_id'] if dept else None,
- user['phonenumber'],
- user['email'],
- user['sex'],
- user['status'],
- [item['post_id'] for item in post if item] or [],
- [item['role_id'] for item in role if item] or [],
- user['remark'],
- {'user_id': user_id},
- {'timestamp': time.time()}
- ]
+ return dict(
+ modal_visible=True,
+ dept_tree=tree_data,
+ form_value=[user.get(k) for k in form_value_list],
+ form_label_validate_status=[None] * len(form_label_list),
+ form_label_validate_info=[None] * len(form_label_list),
+ user_post=[item['post_id'] for item in post if item] or [],
+ user_role=[item['role_id'] for item in role if item] or [],
+ post_option=[dict(label=item['post_name'], value=item['post_id']) for item in post_option if item] or [],
+ role_option=[dict(label=item['role_name'], value=item['role_id']) for item in role_option if item] or [],
+ edit_row_info={'user_id': user_id},
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 14 + [{'timestamp': time.time()}]
+ return dict(
+ modal_visible=dash.no_update,
+ dept_tree=dash.no_update,
+ form_value=[dash.no_update] * len(form_value_list),
+ form_label_validate_status=[dash.no_update] * len(form_label_list),
+ form_label_validate_info=[dash.no_update] * len(form_label_list),
+ user_post=dash.no_update,
+ user_role=dash.no_update,
+ post_option=dash.no_update,
+ role_option=dash.no_update,
+ edit_row_info=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()}
+ )
- return [dash.no_update] * 15
+ raise PreventUpdate
@app.callback(
- [Output('user-edit-nick_name-form-item', 'validateStatus'),
- Output('user-edit-nick_name-form-item', 'help'),
- Output('user-edit-modal', 'visible', allow_duplicate=True),
- Output('user-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('user-edit-modal', 'okCounts'),
- [State('user-edit-nick_name', 'value'),
- State('user-edit-dept_id', 'value'),
- State('user-edit-phone_number', 'value'),
- State('user-edit-email', 'value'),
- State('user-edit-sex', 'value'),
- State('user-edit-status', 'value'),
- State('user-edit-post', 'value'),
- State('user-edit-role', 'value'),
- State('user-edit-remark', 'value'),
- State('user-edit-id-store', 'data')],
+ output=dict(
+ form_label_validate_status=Output({'type': 'user_edit-form-label', 'index': ALL, 'required': True}, 'validateStatus', allow_duplicate=True),
+ form_label_validate_info=Output({'type': 'user_edit-form-label', 'index': ALL, 'required': True}, 'help', allow_duplicate=True),
+ modal_visible=Output('user-edit-modal', 'visible', allow_duplicate=True),
+ operations=Output('user-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ edit_confirm=Input('user-edit-modal', 'okCounts')
+ ),
+ state=dict(
+ post=State('user-edit-post', 'value'),
+ role=State('user-edit-role', 'value'),
+ edit_row_info=State('user-edit-id-store', 'data'),
+ form_value=State({'type': 'user_edit-form-value', 'index': ALL}, 'value'),
+ form_label=State({'type': 'user_edit-form-label', 'index': ALL, 'required': True}, 'label')
+ ),
prevent_initial_call=True
)
-def usr_edit_confirm(edit_confirm, nick_name, dept_id, phone_number, email, sex, status, post, role, remark, user_id):
+def usr_edit_confirm(edit_confirm, edit_row_info, post, role, form_value, form_label):
if edit_confirm:
-
- if all([nick_name]):
- params = dict(user_id=user_id['user_id'], nick_name=nick_name, dept_id=dept_id if dept_id else -1,
- phonenumber=phone_number, email=email, sex=sex, status=status,
- post_id=','.join(map(str, post)), role_id=','.join(map(str, role)), remark=remark)
+ # 获取所有输出表单项对应label的index
+ form_label_output_list = [x['id']['index'] for x in dash.ctx.outputs_list[0]]
+ # 获取所有输入表单项对应的value及label
+ form_value_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-2]}
+ form_label_state = {x['id']['index']: x.get('value') for x in dash.ctx.states_list[-1]}
+
+ if all([form_value_state.get(k) for k in form_label_output_list]):
+ params = form_value_state
+ params['user_id'] = edit_row_info.get('user_id') if edit_row_info else None
+ params['post_id'] = ','.join(map(str, post)) if post else ''
+ params['role_id'] = ','.join(map(str, role)) if role else ''
edit_button_result = edit_user_api(params)
if edit_button_result['code'] == 200:
- return [
- None,
- None,
- False,
- {'type': 'edit'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑成功', type='success')
- ]
-
- return [
- None,
- None,
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=False,
+ operations={'type': 'edit'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑成功', type='success')
+ )
+
+ return dict(
+ form_label_validate_status=[None] * len(form_label_output_list),
+ form_label_validate_info=[None] * len(form_label_output_list),
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑失败', type='error')
+ )
- return [
- None if nick_name else 'error',
- None if nick_name else '请输入用户昵称!',
- dash.no_update,
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('编辑失败', type='error')
- ]
+ return dict(
+ form_label_validate_status=[None if form_value_state.get(k) else 'error' for k in form_label_output_list],
+ form_label_validate_info=[None if form_value_state.get(k) else f'{form_label_state.get(k)}不能为空!' for k in form_label_output_list],
+ modal_visible=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('编辑失败', type='error')
+ )
- return [dash.no_update] * 6
+ raise PreventUpdate
@app.callback(
@@ -460,6 +530,9 @@ def usr_edit_confirm(edit_confirm, nick_name, dept_id, phone_number, email, sex,
prevent_initial_call=True
)
def table_switch_user_status(recently_switch_data_index, recently_switch_status, recently_switch_row):
+ """
+ 表格内切换用户状态回调
+ """
if recently_switch_data_index:
if recently_switch_status:
params = dict(user_id=int(recently_switch_row['key']), status='0', type='status')
@@ -475,12 +548,12 @@ def table_switch_user_status(recently_switch_data_index, recently_switch_status,
]
return [
- dash.no_update,
+ {'type': 'switch-status'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('修改失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -496,6 +569,9 @@ def table_switch_user_status(recently_switch_data_index, recently_switch_status,
)
def user_delete_modal(operation_click, dropdown_click,
selected_row_keys, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row):
+ """
+ 显示删除用户二次确认弹窗回调
+ """
trigger_id = dash.ctx.triggered_id
if trigger_id == {'index': 'delete', 'type': 'user-operation-button'} or (trigger_id == 'user-list-table' and recently_clicked_dropdown_item_title == '删除'):
@@ -505,7 +581,7 @@ def user_delete_modal(operation_click, dropdown_click,
if recently_clicked_dropdown_item_title == '删除':
user_ids = recently_dropdown_item_clicked_row['key']
else:
- return [dash.no_update] * 3
+ raise PreventUpdate
return [
f'是否确认删除用户编号为{user_ids}的用户?',
@@ -513,7 +589,7 @@ def user_delete_modal(operation_click, dropdown_click,
{'user_ids': user_ids}
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -525,6 +601,9 @@ def user_delete_modal(operation_click, dropdown_click,
prevent_initial_call=True
)
def user_delete_confirm(delete_confirm, user_ids_data):
+ """
+ 删除用户弹窗确认回调,实现删除操作
+ """
if delete_confirm:
params = user_ids_data
@@ -542,7 +621,7 @@ def user_delete_confirm(delete_confirm, user_ids_data):
fuc.FefferyFancyMessage('删除失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -555,11 +634,14 @@ def user_delete_confirm(delete_confirm, user_ids_data):
prevent_initial_call=True
)
def user_reset_password_modal(dropdown_click, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row):
+ """
+ 显示重置用户密码弹窗回调
+ """
if dropdown_click:
if recently_clicked_dropdown_item_title == '重置密码':
user_id = recently_dropdown_item_clicked_row['key']
else:
- return [dash.no_update] * 3
+ raise PreventUpdate
return [
True,
@@ -567,7 +649,7 @@ def user_reset_password_modal(dropdown_click, recently_clicked_dropdown_item_tit
None
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -580,6 +662,9 @@ def user_reset_password_modal(dropdown_click, recently_clicked_dropdown_item_tit
prevent_initial_call=True
)
def user_reset_password_confirm(reset_confirm, user_id_data, reset_password):
+ """
+ 重置用户密码弹窗确认回调,实现重置密码操作
+ """
if reset_confirm:
user_id_data['password'] = reset_password
@@ -598,7 +683,7 @@ def user_reset_password_confirm(reset_confirm, user_id_data, reset_password):
fuc.FefferyFancyMessage('重置失败', type='error')
]
- return [dash.no_update] * 3
+ raise PreventUpdate
@app.callback(
@@ -612,6 +697,9 @@ def user_reset_password_confirm(reset_confirm, user_id_data, reset_password):
prevent_initial_call=True
)
def role_to_allocated_user_modal(dropdown_click, recently_clicked_dropdown_item_title, recently_dropdown_item_clicked_row, allocated_role_search_nclick):
+ """
+ 显示用户分配角色弹窗回调
+ """
if dropdown_click and recently_clicked_dropdown_item_title == '分配角色':
return [
@@ -620,9 +708,10 @@ def role_to_allocated_user_modal(dropdown_click, recently_clicked_dropdown_item_
recently_dropdown_item_clicked_row['key']
]
- return [dash.no_update] * 3
+ raise PreventUpdate
+# 显示用户导入弹窗及重置上传弹窗组件状态回调
app.clientside_callback(
'''
(nClicks) => {
@@ -652,52 +741,61 @@ app.clientside_callback(
@app.callback(
- [Output('user-import-confirm-modal', 'confirmLoading'),
- Output('batch-result-modal', 'visible'),
- Output('batch-result-content', 'children'),
- Output('user-operations-store', 'data', allow_duplicate=True),
- Output('api-check-token', 'data', allow_duplicate=True),
- Output('global-message-container', 'children', allow_duplicate=True)],
- Input('user-import-confirm-modal', 'okCounts'),
- [State('user-upload-choose', 'listUploadTaskRecord'),
- State('user-import-update-check', 'checked')],
+ output=dict(
+ confirm_loading=Output('user-import-confirm-modal', 'confirmLoading'),
+ modal_visible=Output('batch-result-modal', 'visible'),
+ batch_result=Output('batch-result-content', 'children'),
+ operations=Output('user-operations-store', 'data', allow_duplicate=True),
+ api_check_token_trigger=Output('api-check-token', 'data', allow_duplicate=True),
+ global_message_container=Output('global-message-container', 'children', allow_duplicate=True)
+ ),
+ inputs=dict(
+ import_confirm=Input('user-import-confirm-modal', 'okCounts')
+ ),
+ state=dict(
+ list_upload_task_record=State('user-upload-choose', 'listUploadTaskRecord'),
+ is_update=State('user-import-update-check', 'checked')
+ ),
prevent_initial_call=True
)
def user_import_confirm(import_confirm, list_upload_task_record, is_update):
+ """
+ 用户导入弹窗确认回调,实现批量导入用户操作
+ """
if import_confirm:
if list_upload_task_record:
url = list_upload_task_record[-1].get('url')
batch_param = dict(url=url, is_update=is_update)
batch_import_result = batch_import_user_api(batch_param)
if batch_import_result.get('code') == 200:
- return [
- False,
- True if batch_import_result.get('message') else False,
- batch_import_result.get('message'),
- {'type': 'batch-import'},
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('导入成功', type='success')
- ]
-
- return [
- False,
- True,
- batch_import_result.get('message'),
- dash.no_update,
- {'timestamp': time.time()},
- fuc.FefferyFancyMessage('导入失败', type='error')
- ]
+ return dict(
+ confirm_loading=False,
+ modal_visible=True if batch_import_result.get('message') else False,
+ batch_result=batch_import_result.get('message'),
+ operations={'type': 'batch-import'},
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('导入成功', type='success')
+ )
+
+ return dict(
+ confirm_loading=False,
+ modal_visible=True,
+ batch_result=batch_import_result.get('message'),
+ operations=dash.no_update,
+ api_check_token_trigger={'timestamp': time.time()},
+ global_message_container=fuc.FefferyFancyMessage('导入失败', type='error')
+ )
else:
- return [
- False,
- dash.no_update,
- dash.no_update,
- dash.no_update,
- dash.no_update,
- fuc.FefferyFancyMessage('请上传需要导入的文件', type='error')
- ]
+ return dict(
+ confirm_loading=False,
+ modal_visible=dash.no_update,
+ batch_result=dash.no_update,
+ operations=dash.no_update,
+ api_check_token_trigger=dash.no_update,
+ global_message_container=fuc.FefferyFancyMessage('请上传需要导入的文件', type='error')
+ )
- return [dash.no_update] * 6
+ raise PreventUpdate
@app.callback(
@@ -710,6 +808,9 @@ def user_import_confirm(import_confirm, list_upload_task_record, is_update):
prevent_initial_call=True
)
def export_user_list(export_click, download_click):
+ """
+ 导出用户信息回调
+ """
trigger_id = dash.ctx.triggered_id
if export_click or download_click:
@@ -751,7 +852,7 @@ def export_user_list(export_click, download_click):
fuc.FefferyFancyMessage('下载失败', type='error')
]
- return [dash.no_update] * 4
+ raise PreventUpdate
@app.callback(
@@ -760,9 +861,12 @@ def export_user_list(export_click, download_click):
prevent_initial_call=True
)
def reset_user_export_status(data):
+ """
+ 导出完成后重置下载组件数据回调,防止重复下载文件
+ """
time.sleep(0.5)
if data:
return None
- return dash.no_update
+ raise PreventUpdate
diff --git a/dash-fastapi-frontend/views/monitor/job/__init__.py b/dash-fastapi-frontend/views/monitor/job/__init__.py
index 2ac8bf4a5dc2e72472d62f622389f203f562417a..7785e341dea1a429551ad7703d9b8178b013831c 100644
--- a/dash-fastapi-frontend/views/monitor/job/__init__.py
+++ b/dash-fastapi-frontend/views/monitor/job/__init__.py
@@ -415,13 +415,20 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='job-job_name',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'job_name'
+ },
placeholder='请输入任务名称',
style={
'width': '100%'
}
),
- id='job-job_name-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'job_name',
+ 'required': True
+ },
required=True,
label='任务名称',
labelCol={
@@ -436,14 +443,21 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdSelect(
- id='job-job_group',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'job_group'
+ },
placeholder='请选择任务分组',
options=option,
style={
'width': '100%'
}
),
- id='job-job_group-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'job_group',
+ 'required': False
+ },
label='任务分组',
labelCol={
'span': 6
@@ -462,13 +476,20 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='job-invoke_target',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'invoke_target'
+ },
placeholder='请输入调用目标字符串',
style={
'width': '100%'
}
),
- id='job-invoke_target-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'invoke_target',
+ 'required': True
+ },
required=True,
label='调用方法',
labelCol={
@@ -488,13 +509,20 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='job-job_args',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'job_args'
+ },
placeholder='请输入位置参数',
style={
'width': '100%'
}
),
- id='job-job_args-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'job_args',
+ 'required': False
+ },
label='位置参数',
labelCol={
'span': 6
@@ -508,13 +536,20 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='job-job_kwargs',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'job_kwargs'
+ },
placeholder='请输入关键字参数',
style={
'width': '100%'
}
),
- id='job-job_kwargs-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'job_kwargs',
+ 'required': False
+ },
label='关键字参数',
labelCol={
'span': 6
@@ -533,7 +568,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='job-cron_expression',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'cron_expression'
+ },
placeholder='请输入cron执行表达式',
addonAfter=html.Div(
[
@@ -550,7 +588,11 @@ def render(button_perms):
'width': '100%'
}
),
- id='job-cron_expression-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'cron_expression',
+ 'required': True
+ },
required=True,
label='cron表达式',
labelCol={
@@ -570,7 +612,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='job-misfire_policy',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'misfire_policy'
+ },
options=[
{
'label': '立即执行',
@@ -589,7 +634,11 @@ def render(button_perms):
optionType='button',
buttonStyle='solid'
),
- id='job-misfire_policy-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'misfire_policy',
+ 'required': False
+ },
label='执行策略',
labelCol={
'span': 3
@@ -608,7 +657,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='job-concurrent',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'concurrent'
+ },
options=[
{
'label': '允许',
@@ -623,7 +675,11 @@ def render(button_perms):
optionType='button',
buttonStyle='solid'
),
- id='job-concurrent-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'concurrent',
+ 'required': False
+ },
label='是否并发',
labelCol={
'span': 6
@@ -637,7 +693,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='job-status',
+ id={
+ 'type': 'job-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -650,7 +709,11 @@ def render(button_perms):
],
defaultValue='0',
),
- id='job-status-form-item',
+ id={
+ 'type': 'job-form-label',
+ 'index': 'status',
+ 'required': False
+ },
label='状态',
labelCol={
'span': 6
@@ -707,10 +770,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-job_name-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'job_name'
+ }
+ ),
label='任务名称',
required=True,
- id='job_detail-job_name-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'job_name'
+ },
labelCol={
'span': 8
},
@@ -722,10 +793,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-job_group-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'job_group'
+ }
+ ),
label='任务分组',
required=True,
- id='job_detail-job_group-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'job_group'
+ },
labelCol={
'span': 8
},
@@ -742,10 +821,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-job_executor-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'job_executor'
+ }
+ ),
label='任务执行器',
required=True,
- id='job_detail-job_executor-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'job_executor'
+ },
labelCol={
'span': 8
},
@@ -757,10 +844,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-invoke_target-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'invoke_target'
+ }
+ ),
label='调用目标函数',
required=True,
- id='job_detail-invoke_target-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'invoke_target'
+ },
labelCol={
'span': 8
},
@@ -777,10 +872,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-job_args-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'job_args'
+ }
+ ),
label='位置参数',
required=True,
- id='job_detail-job_args-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'job_args'
+ },
labelCol={
'span': 8
},
@@ -792,10 +895,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-job_kwargs-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'job_kwargs'
+ }
+ ),
label='关键字参数',
required=True,
- id='job_detail-job_kwargs-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'job_kwargs'
+ },
labelCol={
'span': 8
},
@@ -812,10 +923,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-cron_expression-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'cron_expression'
+ }
+ ),
label='cron表达式',
required=True,
- id='job_detail-cron_expression-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'cron_expression'
+ },
labelCol={
'span': 4
},
@@ -831,10 +950,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-misfire_policy-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'misfire_policy'
+ }
+ ),
label='执行策略',
required=True,
- id='job_detail-misfire_policy-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'misfire_policy'
+ },
labelCol={
'span': 8
},
@@ -846,10 +973,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-concurrent-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'concurrent'
+ }
+ ),
label='是否并发',
required=True,
- id='job_detail-concurrent-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'concurrent'
+ },
labelCol={
'span': 8
},
@@ -866,10 +1001,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-status-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'status'
+ }
+ ),
label='任务状态',
required=True,
- id='job_detail-status-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'status'
+ },
labelCol={
'span': 8
},
@@ -881,10 +1024,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_detail-create_time-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_detail-form-value',
+ 'index': 'create_time'
+ }
+ ),
label='创建时间',
required=True,
- id='job_detail-create_time-form-item',
+ id={
+ 'type': 'job_detail-form-label',
+ 'index': 'create_time'
+ },
labelCol={
'span': 8
},
diff --git a/dash-fastapi-frontend/views/monitor/job/job_log.py b/dash-fastapi-frontend/views/monitor/job/job_log.py
index a62f2b200c04f5ce2d6bef98b4b9577a95c7de9f..ba5f97d2086da75bc82e64c85e55d90880e0691d 100644
--- a/dash-fastapi-frontend/views/monitor/job/job_log.py
+++ b/dash-fastapi-frontend/views/monitor/job/job_log.py
@@ -5,7 +5,6 @@ import callbacks.monitor_c.job_c.job_log_c
def render(button_perms):
-
return [
dcc.Store(id='job_log-button-perms-container', data=button_perms),
# 用于导出成功后重置dcc.Download的状态,防止多次下载文件
@@ -311,7 +310,7 @@ def render(button_perms):
gutter=5
),
- # 任务调度日志明细modal
+ # 任务调度日志明细modal,表单项id使用字典类型,index与后端数据库字段一一对应
fac.AntdModal(
[
fac.AntdForm(
@@ -320,10 +319,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_name-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_name'
+ }
+ ),
label='任务名称',
required=True,
- id='job_log-job_name-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_name'
+ },
labelCol={
'span': 8
},
@@ -335,10 +342,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_group-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_group'
+ }
+ ),
label='任务分组',
required=True,
- id='job_log-job_group-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_group'
+ },
labelCol={
'span': 8
},
@@ -355,10 +370,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_executor-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_executor'
+ }
+ ),
label='任务执行器',
required=True,
- id='job_log-job_executor-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_executor'
+ },
labelCol={
'span': 8
},
@@ -370,10 +393,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-invoke_target-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'invoke_target'
+ }
+ ),
label='调用目标字符串',
required=True,
- id='job_log-invoke_target-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'invoke_target'
+ },
labelCol={
'span': 8
},
@@ -390,10 +421,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_args-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_args'
+ }
+ ),
label='位置参数',
required=True,
- id='job_log-job_args-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_args'
+ },
labelCol={
'span': 8
},
@@ -405,10 +444,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_kwargs-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_kwargs'
+ }
+ ),
label='关键字参数',
required=True,
- id='job_log-job_kwargs-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_kwargs'
+ },
labelCol={
'span': 8
},
@@ -425,10 +472,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_trigger-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_trigger'
+ }
+ ),
label='任务触发器',
required=True,
- id='job_log-job_trigger-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_trigger'
+ },
labelCol={
'span': 4
},
@@ -444,10 +499,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-job_message-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'job_message'
+ }
+ ),
label='日志信息',
required=True,
- id='job_log-job_message-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'job_message'
+ },
labelCol={
'span': 4
},
@@ -463,10 +526,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-status-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'status'
+ }
+ ),
label='执行状态',
required=True,
- id='job_log-status-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'status'
+ },
labelCol={
'span': 8
},
@@ -478,10 +549,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-create_time-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'create_time'
+ }
+ ),
label='执行时间',
required=True,
- id='job_log-create_time-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'create_time'
+ },
labelCol={
'span': 8
},
@@ -498,10 +577,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='job_log-exception_info-text'),
+ fac.AntdText(
+ id={
+ 'type': 'job_log-form-value',
+ 'index': 'exception_info'
+ }
+ ),
label='异常信息',
required=True,
- id='job_log-exception_info-form-item',
+ id={
+ 'type': 'job_log-form-label',
+ 'index': 'exception_info'
+ },
labelCol={
'span': 4
},
diff --git a/dash-fastapi-frontend/views/monitor/operlog/__init__.py b/dash-fastapi-frontend/views/monitor/operlog/__init__.py
index 7e41ce51805de37f9c4900c002033ad46e864a99..1ee38e09230b26e8d9018f62b1d461d508218fa1 100644
--- a/dash-fastapi-frontend/views/monitor/operlog/__init__.py
+++ b/dash-fastapi-frontend/views/monitor/operlog/__init__.py
@@ -396,10 +396,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-title-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'title'
+ }
+ ),
label='操作模块',
required=True,
- id='operation_log-title-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'title'
+ },
labelCol={
'span': 8
},
@@ -411,10 +419,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-oper_url-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'oper_url'
+ }
+ ),
label='请求地址',
required=True,
- id='operation_log-oper_url-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'oper_url'
+ },
labelCol={
'span': 8
},
@@ -431,10 +447,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-login_info-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'login_info'
+ }
+ ),
label='登录信息',
required=True,
- id='operation_log-login_info-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'login_info'
+ },
labelCol={
'span': 8
},
@@ -446,10 +470,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-request_method-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'request_method'
+ }
+ ),
label='请求方式',
required=True,
- id='operation_log-request_method-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'request_method'
+ },
labelCol={
'span': 8
},
@@ -466,10 +498,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-method-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'method'
+ }
+ ),
label='操作方法',
required=True,
- id='operation_log-method-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'method'
+ },
labelCol={
'span': 4
},
@@ -485,10 +525,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-oper_param-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'oper_param'
+ }
+ ),
label='请求参数',
required=True,
- id='operation_log-oper_param-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'oper_param'
+ },
labelCol={
'span': 4
},
@@ -504,10 +552,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-json_result-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'json_result'
+ }
+ ),
label='返回参数',
required=True,
- id='operation_log-json_result-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'json_result'
+ },
labelCol={
'span': 4
},
@@ -523,10 +579,18 @@ def render(button_perms):
[
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-status-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'status'
+ }
+ ),
label='操作状态',
required=True,
- id='operation_log-status-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'status'
+ },
labelCol={
'span': 12
},
@@ -538,10 +602,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-cost_time-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'cost_time'
+ }
+ ),
label='消耗时间',
required=True,
- id='operation_log-cost_time-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'cost_time'
+ },
labelCol={
'span': 12
},
@@ -553,10 +625,18 @@ def render(button_perms):
),
fac.AntdCol(
fac.AntdFormItem(
- fac.AntdText(id='operation_log-oper_time-text'),
+ fac.AntdText(
+ id={
+ 'type': 'operation_log-form-value',
+ 'index': 'oper_time'
+ }
+ ),
label='操作时间',
required=True,
- id='operation_log-oper_time-form-item',
+ id={
+ 'type': 'operation_log-form-label',
+ 'index': 'oper_time'
+ },
labelCol={
'span': 8
},
diff --git a/dash-fastapi-frontend/views/system/config/__init__.py b/dash-fastapi-frontend/views/system/config/__init__.py
index c6aabb0c1f9216483da84ee925db0eeba18a26c5..9a3457507f1e526205e535313f6e33ebf671de1e 100644
--- a/dash-fastapi-frontend/views/system/config/__init__.py
+++ b/dash-fastapi-frontend/views/system/config/__init__.py
@@ -393,7 +393,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='config-config_name',
+ id={
+ 'type': 'config-form-value',
+ 'index': 'config_name'
+ },
placeholder='请输入参数名称',
allowClear=True,
style={
@@ -402,7 +405,11 @@ def render(button_perms):
),
label='参数名称',
required=True,
- id='config-config_name-form-item'
+ id={
+ 'type': 'config-form-label',
+ 'index': 'config_name',
+ 'required': True
+ }
),
span=24
),
@@ -413,7 +420,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='config-config_key',
+ id={
+ 'type': 'config-form-value',
+ 'index': 'config_key'
+ },
placeholder='请输入参数键名',
allowClear=True,
style={
@@ -422,7 +432,11 @@ def render(button_perms):
),
label='参数键名',
required=True,
- id='config-config_key-form-item'
+ id={
+ 'type': 'config-form-label',
+ 'index': 'config_key',
+ 'required': True
+ }
),
span=24
),
@@ -433,7 +447,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='config-config_value',
+ id={
+ 'type': 'config-form-value',
+ 'index': 'config_value'
+ },
placeholder='请输入参数键值',
allowClear=True,
style={
@@ -442,7 +459,11 @@ def render(button_perms):
),
label='参数键值',
required=True,
- id='config-config_value-form-item'
+ id={
+ 'type': 'config-form-label',
+ 'index': 'config_value',
+ 'required': True
+ }
),
span=24
),
@@ -453,7 +474,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='config-config_type',
+ id={
+ 'type': 'config-form-value',
+ 'index': 'config_type'
+ },
options=[
{
'label': '是',
@@ -470,7 +494,11 @@ def render(button_perms):
}
),
label='系统内置',
- id='config-config_type-form-item'
+ id={
+ 'type': 'config-form-label',
+ 'index': 'config_type',
+ 'required': False
+ }
),
span=24
),
@@ -481,7 +509,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='config-remark',
+ id={
+ 'type': 'config-form-value',
+ 'index': 'remark'
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -490,7 +521,11 @@ def render(button_perms):
}
),
label='备注',
- id='config-remark-form-item'
+ id={
+ 'type': 'config-form-label',
+ 'index': 'remark',
+ 'required': False
+ }
),
span=24
),
diff --git a/dash-fastapi-frontend/views/system/dept/__init__.py b/dash-fastapi-frontend/views/system/dept/__init__.py
index b5d2a299111f1c27a06f91faee7da1719d4427c9..bc8de1b4b673d7b0da5aadf076c1023395f14a30 100644
--- a/dash-fastapi-frontend/views/system/dept/__init__.py
+++ b/dash-fastapi-frontend/views/system/dept/__init__.py
@@ -329,7 +329,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdTreeSelect(
- id='dept-parent_id',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'parent_id'
+ },
placeholder='请选择上级部门',
treeData=[],
treeNodeFilterProp='title',
@@ -339,7 +342,11 @@ def render(button_perms):
),
label='上级部门',
required=True,
- id='dept-parent_id-form-item',
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'parent_id',
+ 'required': True
+ },
labelCol={
'span': 4
},
@@ -360,7 +367,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dept-dept_name',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'dept_name'
+ },
placeholder='请输入部门名称',
allowClear=True,
style={
@@ -369,14 +379,21 @@ def render(button_perms):
),
label='部门名称',
required=True,
- id='dept-dept_name-form-item'
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'dept_name',
+ 'required': True
+ }
),
span=12
),
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInputNumber(
- id='dept-order_num',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'order_num'
+ },
min=0,
style={
'width': '100%'
@@ -384,7 +401,11 @@ def render(button_perms):
),
label='显示顺序',
required=True,
- id='dept-order_num-form-item'
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'order_num',
+ 'required': True
+ }
),
span=12
)
@@ -396,7 +417,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dept-leader',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'leader'
+ },
placeholder='请输入负责人',
allowClear=True,
style={
@@ -404,14 +428,21 @@ def render(button_perms):
}
),
label='负责人',
- id='dept-leader-form-item'
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'leader',
+ 'required': False
+ }
),
span=12
),
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dept-phone',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'phone'
+ },
placeholder='请输入联系电话',
allowClear=True,
style={
@@ -419,7 +450,11 @@ def render(button_perms):
}
),
label='联系电话',
- id='dept-phone-form-item'
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'phone',
+ 'required': False
+ }
),
span=12
),
@@ -431,7 +466,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dept-email',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'email'
+ },
placeholder='请输入邮箱',
allowClear=True,
style={
@@ -439,14 +477,21 @@ def render(button_perms):
}
),
label='邮箱',
- id='dept-email-form-item'
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'email',
+ 'required': False
+ }
),
span=12
),
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='dept-status',
+ id={
+ 'type': 'dept-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -463,7 +508,11 @@ def render(button_perms):
}
),
label='部门状态',
- id='dept-status-form-item'
+ id={
+ 'type': 'dept-form-label',
+ 'index': 'status',
+ 'required': False
+ }
),
span=12
),
diff --git a/dash-fastapi-frontend/views/system/dict/__init__.py b/dash-fastapi-frontend/views/system/dict/__init__.py
index a3b0a1f581cb085739d3c9377f7eb84e6299e5ae..608f59ee035c4a89c78d092a150f97118960663d 100644
--- a/dash-fastapi-frontend/views/system/dict/__init__.py
+++ b/dash-fastapi-frontend/views/system/dict/__init__.py
@@ -394,7 +394,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_type-dict_name',
+ id={
+ 'type': 'dict_type-form-value',
+ 'index': 'dict_name'
+ },
placeholder='请输入字典名称',
allowClear=True,
style={
@@ -403,7 +406,11 @@ def render(button_perms):
),
label='字典名称',
required=True,
- id='dict_type-dict_name-form-item'
+ id={
+ 'type': 'dict_type-form-label',
+ 'index': 'dict_name',
+ 'required': True
+ }
),
span=24
),
@@ -414,7 +421,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_type-dict_type',
+ id={
+ 'type': 'dict_type-form-value',
+ 'index': 'dict_type'
+ },
placeholder='请输入字典类型',
allowClear=True,
style={
@@ -423,7 +433,11 @@ def render(button_perms):
),
label='字典类型',
required=True,
- id='dict_type-dict_type-form-item'
+ id={
+ 'type': 'dict_type-form-label',
+ 'index': 'dict_type',
+ 'required': True
+ }
),
span=24
),
@@ -434,7 +448,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='dict_type-status',
+ id={
+ 'type': 'dict_type-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -451,7 +468,11 @@ def render(button_perms):
}
),
label='状态',
- id='dict_type-status-form-item'
+ id={
+ 'type': 'dict_type-form-label',
+ 'index': 'status',
+ 'required': False
+ }
),
span=24
),
@@ -462,7 +483,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_type-remark',
+ id={
+ 'type': 'dict_type-form-value',
+ 'index': 'remark'
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -471,7 +495,11 @@ def render(button_perms):
}
),
label='备注',
- id='dict_type-remark-form-item'
+ id={
+ 'type': 'dict_type-form-label',
+ 'index': 'remark',
+ 'required': False
+ }
),
span=24
),
diff --git a/dash-fastapi-frontend/views/system/dict/dict_data.py b/dash-fastapi-frontend/views/system/dict/dict_data.py
index 57aa97ef4b649c1134c7de6e5f0a07c2e1ef9850..6352390e0b91c00ab6ec492111fd8a8d6d285110 100644
--- a/dash-fastapi-frontend/views/system/dict/dict_data.py
+++ b/dash-fastapi-frontend/views/system/dict/dict_data.py
@@ -333,7 +333,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_data-dict_type',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'dict_type'
+ },
placeholder='请输入字典类型',
disabled=True,
style={
@@ -341,7 +344,11 @@ def render(button_perms):
}
),
label='字典类型',
- id='dict_data-dict_type-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'dict_type',
+ 'required': False
+ }
),
span=24
),
@@ -352,7 +359,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_data-dict_label',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'dict_label'
+ },
placeholder='请输入数据标签',
allowClear=True,
style={
@@ -361,7 +371,11 @@ def render(button_perms):
),
label='数据标签',
required=True,
- id='dict_data-dict_label-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'dict_label',
+ 'required': True
+ }
),
span=24
),
@@ -372,7 +386,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_data-dict_value',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'dict_value'
+ },
placeholder='请输入数据键值',
allowClear=True,
style={
@@ -381,7 +398,11 @@ def render(button_perms):
),
label='数据键值',
required=True,
- id='dict_data-dict_value-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'dict_value',
+ 'required': True
+ }
),
span=24
),
@@ -392,7 +413,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_data-css_class',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'css_class'
+ },
placeholder='请输入样式属性',
allowClear=True,
style={
@@ -400,7 +424,11 @@ def render(button_perms):
}
),
label='样式属性',
- id='dict_data-css_class-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'css_class',
+ 'required': False
+ }
),
span=24
),
@@ -411,7 +439,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInputNumber(
- id='dict_data-dict_sort',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'dict_sort'
+ },
defaultValue=0,
min=0,
style={
@@ -420,7 +451,11 @@ def render(button_perms):
),
label='显示排序',
required=True,
- id='dict_data-dict_sort-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'dict_sort',
+ 'required': True
+ }
),
span=24
),
@@ -431,7 +466,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdSelect(
- id='dict_data-list_class',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'list_class'
+ },
placeholder='回显样式',
options=[
{
@@ -464,7 +502,11 @@ def render(button_perms):
}
),
label='回显样式',
- id='dict_data-list_class-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'list_class',
+ 'required': False
+ }
),
span=24
),
@@ -475,7 +517,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='dict_data-status',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -492,7 +537,11 @@ def render(button_perms):
}
),
label='状态',
- id='dict_data-status-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'status',
+ 'required': False
+ }
),
span=24
),
@@ -503,7 +552,10 @@ def render(button_perms):
fac.AntdCol(
fac.AntdFormItem(
fac.AntdInput(
- id='dict_data-remark',
+ id={
+ 'type': 'dict_data-form-value',
+ 'index': 'remark'
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -512,7 +564,11 @@ def render(button_perms):
}
),
label='备注',
- id='dict_data-remark-form-item'
+ id={
+ 'type': 'dict_data-form-label',
+ 'index': 'remark',
+ 'required': False
+ }
),
span=24
),
diff --git a/dash-fastapi-frontend/views/system/post/__init__.py b/dash-fastapi-frontend/views/system/post/__init__.py
index a3110e890be5c7b2b44bf40c380353b7d65873ef..af668e8c10aa69da5ed50eaa816fb02b1cc4d1fd 100644
--- a/dash-fastapi-frontend/views/system/post/__init__.py
+++ b/dash-fastapi-frontend/views/system/post/__init__.py
@@ -360,7 +360,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='post-post_name',
+ id={
+ 'type': 'post-form-value',
+ 'index': 'post_name'
+ },
placeholder='请输入岗位名称',
allowClear=True,
style={
@@ -369,11 +372,18 @@ def render(button_perms):
),
label='岗位名称',
required=True,
- id='post-post_name-form-item'
+ id={
+ 'type': 'post-form-label',
+ 'index': 'post_name',
+ 'required': True
+ }
),
fac.AntdFormItem(
fac.AntdInput(
- id='post-post_code',
+ id={
+ 'type': 'post-form-value',
+ 'index': 'post_code'
+ },
placeholder='请输入岗位编码',
allowClear=True,
style={
@@ -382,11 +392,18 @@ def render(button_perms):
),
label='岗位编码',
required=True,
- id='post-post_code-form-item'
+ id={
+ 'type': 'post-form-label',
+ 'index': 'post_code',
+ 'required': True
+ }
),
fac.AntdFormItem(
fac.AntdInputNumber(
- id='post-post_sort',
+ id={
+ 'type': 'post-form-value',
+ 'index': 'post_sort'
+ },
defaultValue=0,
min=0,
style={
@@ -395,11 +412,18 @@ def render(button_perms):
),
label='岗位顺序',
required=True,
- id='post-post_sort-form-item'
+ id={
+ 'type': 'post-form-label',
+ 'index': 'post_sort',
+ 'required': True
+ }
),
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='post-status',
+ id={
+ 'type': 'post-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -416,11 +440,18 @@ def render(button_perms):
}
),
label='岗位状态',
- id='post-status-form-item'
+ id={
+ 'type': 'post-form-label',
+ 'index': 'status',
+ 'required': False
+ }
),
fac.AntdFormItem(
fac.AntdInput(
- id='post-remark',
+ id={
+ 'type': 'post-form-value',
+ 'index': 'remark'
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -429,7 +460,11 @@ def render(button_perms):
}
),
label='备注',
- id='post-remark-form-item'
+ id={
+ 'type': 'post-form-label',
+ 'index': 'remark',
+ 'required': False
+ }
),
],
labelCol={
diff --git a/dash-fastapi-frontend/views/system/role/__init__.py b/dash-fastapi-frontend/views/system/role/__init__.py
index 073ff9b96526ff8d54cd470a2f2de4f9c1d810c3..212fce1e12219eaa28fc8c2dcf93adf0dba10997 100644
--- a/dash-fastapi-frontend/views/system/role/__init__.py
+++ b/dash-fastapi-frontend/views/system/role/__init__.py
@@ -21,9 +21,9 @@ def render(button_perms):
total = table_info['data']['total']
for item in table_data:
if item['status'] == '0':
- item['status'] = dict(checked=True)
+ item['status'] = dict(checked=True, disabled=item['role_id'] == 1)
else:
- item['status'] = dict(checked=False)
+ item['status'] = dict(checked=False, disabled=item['role_id'] == 1)
item['key'] = str(item['role_id'])
if item['role_id'] == 1:
item['operation'] = []
@@ -409,6 +409,7 @@ def render(button_perms):
},
{
'title': '操作',
+ 'width': 180,
'dataIndex': 'operation',
}
],
@@ -448,7 +449,11 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='role-role_name',
+ id={
+ 'type': 'role-form-value',
+ 'index': 'role_name',
+ 'required': True
+ },
placeholder='请输入角色名称',
allowClear=True,
style={
@@ -457,7 +462,11 @@ def render(button_perms):
),
label='角色名称',
required=True,
- id='role-role_name-form-item',
+ id={
+ 'type': 'role-form-label',
+ 'index': 'role_name',
+ 'required': True
+ },
labelCol={
'span': 6
},
@@ -467,7 +476,11 @@ def render(button_perms):
),
fac.AntdFormItem(
fac.AntdInput(
- id='role-role_key',
+ id={
+ 'type': 'role-form-value',
+ 'index': 'role_key',
+ 'required': True
+ },
placeholder='请输入权限字符',
allowClear=True,
style={
@@ -486,7 +499,11 @@ def render(button_perms):
]
),
required=True,
- id='role-role_Key-form-item',
+ id={
+ 'type': 'role-form-label',
+ 'index': 'role_key',
+ 'required': True
+ },
labelCol={
'span': 6
},
@@ -496,7 +513,11 @@ def render(button_perms):
),
fac.AntdFormItem(
fac.AntdInputNumber(
- id='role-role_sort',
+ id={
+ 'type': 'role-form-value',
+ 'index': 'role_sort',
+ 'required': True
+ },
placeholder='请输入角色顺序',
defaultValue=0,
min=0,
@@ -506,7 +527,11 @@ def render(button_perms):
),
label='角色顺序',
required=True,
- id='role-role_sort-form-item',
+ id={
+ 'type': 'role-form-label',
+ 'index': 'role_sort',
+ 'required': True
+ },
labelCol={
'span': 6
},
@@ -516,7 +541,11 @@ def render(button_perms):
),
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='role-status',
+ id={
+ 'type': 'role-form-value',
+ 'index': 'status',
+ 'required': False
+ },
options=[
{
'label': '正常',
@@ -532,7 +561,11 @@ def render(button_perms):
}
),
label='状态',
- id='role-status-form-item',
+ id={
+ 'type': 'role-form-label',
+ 'index': 'status',
+ 'required': False
+ },
labelCol={
'span': 6
},
@@ -607,7 +640,11 @@ def render(button_perms):
),
fac.AntdFormItem(
fac.AntdInput(
- id='role-remark',
+ id={
+ 'type': 'role-form-value',
+ 'index': 'remark',
+ 'required': False
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -616,7 +653,11 @@ def render(button_perms):
}
),
label='备注',
- id='role-remark-form-item',
+ id={
+ 'type': 'role-form-label',
+ 'index': 'remark',
+ 'required': False
+ },
labelCol={
'span': 6
},
diff --git a/dash-fastapi-frontend/views/system/user/__init__.py b/dash-fastapi-frontend/views/system/user/__init__.py
index 498ba1637c887d0f71fcc6fae4e02234b0cbf88c..34651a886ac670935e9a2e7b58af2c096c9e4193 100644
--- a/dash-fastapi-frontend/views/system/user/__init__.py
+++ b/dash-fastapi-frontend/views/system/user/__init__.py
@@ -449,7 +449,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-add-nick_name',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'nick_name'
+ },
placeholder='请输入用户昵称',
allowClear=True,
style={
@@ -458,11 +461,18 @@ def render(button_perms):
),
label='用户昵称',
required=True,
- id='user-add-nick_name-form-item'
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'nick_name',
+ 'required': True
+ }
),
fac.AntdFormItem(
fac.AntdTreeSelect(
- id='user-add-dept_id',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'dept_id'
+ },
placeholder='请选择归属部门',
treeData=[],
treeNodeFilterProp='title',
@@ -471,7 +481,11 @@ def render(button_perms):
}
),
label='归属部门',
- id='user-add-dept_id-form-item',
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'dept_id',
+ 'required': False
+ },
labelCol={
'offset': 1
},
@@ -483,7 +497,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-add-phone_number',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'phonenumber'
+ },
placeholder='请输入手机号码',
allowClear=True,
style={
@@ -491,14 +508,21 @@ def render(button_perms):
}
),
label='手机号码',
- id='user-add-phone_number-form-item',
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'phonenumber',
+ 'required': False
+ },
labelCol={
'offset': 1
},
),
fac.AntdFormItem(
fac.AntdInput(
- id='user-add-email',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'email'
+ },
placeholder='请输入邮箱',
allowClear=True,
style={
@@ -506,7 +530,11 @@ def render(button_perms):
}
),
label='邮箱',
- id='user-add-email-form-item',
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'email',
+ 'required': False
+ },
labelCol={
'offset': 5
},
@@ -518,7 +546,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-add-user_name',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'user_name'
+ },
placeholder='请输入用户名称',
allowClear=True,
style={
@@ -527,11 +558,18 @@ def render(button_perms):
),
label='用户名称',
required=True,
- id='user-add-user_name-form-item'
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'user_name',
+ 'required': True
+ }
),
fac.AntdFormItem(
fac.AntdInput(
- id='user-add-password',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'password'
+ },
placeholder='请输入密码',
mode='password',
passwordUseMd5=True,
@@ -541,7 +579,11 @@ def render(button_perms):
),
label='用户密码',
required=True,
- id='user-add-password-form-item'
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'password',
+ 'required': True
+ }
),
],
size="middle"
@@ -550,7 +592,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdSelect(
- id='user-add-sex',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'sex'
+ },
placeholder='请选择性别',
options=[
{
@@ -571,14 +616,21 @@ def render(button_perms):
}
),
label='用户性别',
- id='user-add-sex-form-item',
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'sex',
+ 'required': False
+ },
labelCol={
'offset': 1
},
),
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='user-add-status',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -595,7 +647,11 @@ def render(button_perms):
}
),
label='用户状态',
- id='user-add-status-form-item',
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'status',
+ 'required': False
+ },
labelCol={
'offset': 2
},
@@ -646,7 +702,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-add-remark',
+ id={
+ 'type': 'user_add-form-value',
+ 'index': 'remark'
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -655,7 +714,11 @@ def render(button_perms):
}
),
label='备注',
- id='user-add-remark-form-item',
+ id={
+ 'type': 'user_add-form-label',
+ 'index': 'remark',
+ 'required': False
+ },
labelCol={
'offset': 2
},
@@ -682,7 +745,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-edit-nick_name',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'nick_name'
+ },
placeholder='请输入用户昵称',
allowClear=True,
style={
@@ -691,11 +757,18 @@ def render(button_perms):
),
label='用户昵称',
required=True,
- id='user-edit-nick_name-form-item'
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'nick_name',
+ 'required': True
+ }
),
fac.AntdFormItem(
fac.AntdTreeSelect(
- id='user-edit-dept_id',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'dept_id'
+ },
placeholder='请选择归属部门',
treeData=[],
treeNodeFilterProp='title',
@@ -704,7 +777,11 @@ def render(button_perms):
}
),
label='归属部门',
- id='user-edit-dept_id-form-item'
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'dept_id',
+ 'required': False
+ }
),
],
size="middle"
@@ -713,7 +790,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-edit-phone_number',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'phonenumber'
+ },
placeholder='请输入手机号码',
allowClear=True,
style={
@@ -721,14 +801,21 @@ def render(button_perms):
}
),
label='手机号码',
- id='user-edit-phone_number-form-item',
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'phonenumber',
+ 'required': False
+ },
labelCol={
'offset': 1
},
),
fac.AntdFormItem(
fac.AntdInput(
- id='user-edit-email',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'email'
+ },
placeholder='请输入邮箱',
allowClear=True,
style={
@@ -736,7 +823,11 @@ def render(button_perms):
}
),
label='邮箱',
- id='user-edit-email-form-item',
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'email',
+ 'required': False
+ },
labelCol={
'offset': 4
},
@@ -748,7 +839,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdSelect(
- id='user-edit-sex',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'sex'
+ },
placeholder='请选择性别',
options=[
{
@@ -769,14 +863,21 @@ def render(button_perms):
}
),
label='用户性别',
- id='user-edit-sex-form-item',
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'sex',
+ 'required': False
+ },
labelCol={
'offset': 1
},
),
fac.AntdFormItem(
fac.AntdRadioGroup(
- id='user-edit-status',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'status'
+ },
options=[
{
'label': '正常',
@@ -792,7 +893,11 @@ def render(button_perms):
}
),
label='用户状态',
- id='user-edit-status-form-item',
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'status',
+ 'required': False
+ },
labelCol={
'offset': 1
},
@@ -843,7 +948,10 @@ def render(button_perms):
[
fac.AntdFormItem(
fac.AntdInput(
- id='user-edit-remark',
+ id={
+ 'type': 'user_edit-form-value',
+ 'index': 'remark'
+ },
placeholder='请输入内容',
allowClear=True,
mode='text-area',
@@ -852,7 +960,11 @@ def render(button_perms):
}
),
label='备注',
- id='user-edit-remark-form-item',
+ id={
+ 'type': 'user_edit-form-label',
+ 'index': 'remark',
+ 'required': False
+ },
labelCol={
'offset': 2
},
diff --git a/demo-pictures/dashzsxq.jpg b/demo-pictures/dashzsxq.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2f7be556491f9c54ea01353dbf805d6a61d14fab
Binary files /dev/null and b/demo-pictures/dashzsxq.jpg differ
diff --git a/demo-pictures/wxcode.jpg b/demo-pictures/wxcode.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2d9a0b1d589e5c4dab0715704cb3f943d553def0
Binary files /dev/null and b/demo-pictures/wxcode.jpg differ
diff --git a/requirements.txt b/requirements.txt
index 7674277651db03adb803c70a1678c6b8fe64fbc2..f6cbbfeb5df8893342bd100e51344959d67da6f0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -23,7 +23,7 @@ email-validator==2.0.0.post2
et-xmlfile==1.1.0
fastapi==0.95.1
feffery-antd-charts==0.0.1rc17
-feffery-antd-components==0.2.9
+feffery-antd-components==0.2.10rc17
feffery-markdown-components==0.2.10
feffery-utils-components==0.1.28
Flask==2.2.5
@@ -50,7 +50,6 @@ Pillow==10.0.0
plotly==5.14.1
ply==3.11
psutil==5.9.5
-psycopg2==2.9.6
pyasn1==0.5.0
pycparser==2.21
pydantic==1.10.7