You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

873 lines
35 KiB

import dash
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
from utils.common import validate_data_not_empty
from api.dept import get_dept_tree_api
from api.user import get_user_list_api, get_user_detail_api, add_user_api, edit_user_api, delete_user_api, reset_user_password_api, batch_import_user_api, download_user_import_template_api, export_user_list_api
from api.role import get_role_select_option_api
from api.post import get_post_select_option_api
@app.callback(
[Output('dept-tree', 'treeData'),
Output('api-check-token', 'data', allow_duplicate=True)],
Input('dept-input-search', 'value'),
prevent_initial_call=True
)
def get_search_dept_tree(dept_input):
dept_params = dict(dept_name=dept_input)
tree_info = get_dept_tree_api(dept_params)
if tree_info['code'] == 200:
tree_data = tree_info['data']
return [tree_data, {'timestamp': time.time()}]
return [dash.no_update, {'timestamp': time.time()}]
@app.callback(
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
if create_time_range:
create_time_start = create_time_range[0]
create_time_end = create_time_range[1]
if selected_dept_tree:
dept_id = int(selected_dept_tree[0])
query_params = dict(
dept_id=dept_id,
user_name=user_name,
phonenumber=phone_number,
status=status_select,
create_time_start=create_time_start,
create_time_end=create_time_end,
page_num=1,
page_size=10
)
triggered_id = dash.ctx.triggered_id
if triggered_id == 'user-list-table':
query_params = dict(
dept_id=dept_id,
user_name=user_name,
phonenumber=phone_number,
status=status_select,
create_time_start=create_time_start,
create_time_end=create_time_end,
page_num=pagination['current'],
page_size=pagination['pageSize']
)
if selected_dept_tree or search_click or refresh_click or pagination or operations:
table_info = get_user_list_api(query_params)
if table_info['code'] == 200:
table_data = table_info['data']['rows']
table_pagination = dict(
pageSize=table_info['data']['page_size'],
current=table_info['data']['page_num'],
showSizeChanger=True,
pageSizeOptions=[10, 30, 50, 100],
showQuickJumper=True,
total=table_info['data']['total']
)
for item in table_data:
if item['status'] == '0':
item['status'] = dict(checked=True, disabled=item['user_id'] == 1)
else:
item['status'] = dict(checked=False, disabled=item['user_id'] == 1)
item['key'] = str(item['user_id'])
if item['user_id'] == 1:
item['operation'] = []
else:
item['operation'] = [
{
'title': '修改',
'icon': 'antd-edit'
} if 'system:user:edit' in button_perms else None,
{
'title': '删除',
'icon': 'antd-delete'
} if 'system:user:remove' in button_perms else None,
{
'title': '重置密码',
'icon': 'antd-key'
} if 'system:user:resetPwd' in button_perms else None,
{
'title': '分配角色',
'icon': 'antd-check-circle'
} if 'system:user:edit' in button_perms else None
]
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 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()}
)
raise PreventUpdate
# 重置用户搜索表单数据回调
app.clientside_callback(
'''
(reset_click) => {
if (reset_click) {
return [null, null, null, null, null, {'type': 'reset'}]
}
return window.dash_clientside.no_update;
}
''',
[Output('dept-tree', 'selectedKeys'),
Output('user-user_name-input', 'value'),
Output('user-phone_number-input', 'value'),
Output('user-status-select', 'value'),
Output('user-create_time-range', 'value'),
Output('user-operations-store', 'data')],
Input('user-reset', 'nClicks'),
prevent_initial_call=True
)
# 隐藏/显示用户搜索表单回调
app.clientside_callback(
'''
(hidden_click, hidden_status) => {
if (hidden_click) {
return [
!hidden_status,
hidden_status ? '隐藏搜索' : '显示搜索'
]
}
return window.dash_clientside.no_update;
}
''',
[Output('user-search-form-container', 'hidden'),
Output('user-hidden-tooltip', 'title')],
Input('user-hidden', 'nClicks'),
State('user-search-form-container', 'hidden'),
prevent_initial_call=True
)
@app.callback(
Output({'type': 'user-operation-button', 'index': 'edit'}, 'disabled'),
Input('user-list-table', 'selectedRowKeys'),
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:
if len(table_rows_selected) > 1 or '1' in table_rows_selected:
return True
return False
return True
raise PreventUpdate
@app.callback(
Output({'type': 'user-operation-button', 'index': 'delete'}, 'disabled'),
Input('user-list-table', 'selectedRowKeys'),
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
return False
return True
raise PreventUpdate
@app.callback(
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()
role_option_info = get_role_select_option_api()
if tree_info['code'] == 200 and post_option_info['code'] == 200 and role_option_info['code'] == 200:
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 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()}
)
raise PreventUpdate
@app.callback(
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, post, role, form_value, form_label):
if add_confirm:
# 获取所有输出表单项对应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(validate_data_not_empty(item) for item in [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 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 dict(
form_label_validate_status=[None if validate_data_not_empty(form_value_state.get(k)) else 'error' for k in form_label_output_list],
form_label_validate_info=[None if validate_data_not_empty(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=dash.no_update,
global_message_container=fuc.FefferyFancyMessage('新增失败', type='error')
)
raise PreventUpdate
@app.callback(
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']
post_option = get_post_select_option_api()['data']
role_option = get_role_select_option_api()['data']
if trigger_id == {'index': 'edit', 'type': 'user-operation-button'}:
user_id = int(selected_row_keys[0])
else:
if recently_clicked_dropdown_item_title == '修改':
user_id = int(recently_dropdown_item_clicked_row['key'])
else:
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']
role = edit_button_result['role']
post = edit_button_result['post']
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 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()}
)
raise PreventUpdate
@app.callback(
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, edit_row_info, post, role, form_value, form_label):
if edit_confirm:
# 获取所有输出表单项对应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(validate_data_not_empty(item) for item in [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 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 validate_data_not_empty(form_value_state.get(k)) else 'error' for k in form_label_output_list],
form_label_validate_info=[None if validate_data_not_empty(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=dash.no_update,
global_message_container=fuc.FefferyFancyMessage('编辑失败', type='error')
)
raise PreventUpdate
@app.callback(
[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-list-table', 'recentlySwitchDataIndex'),
Input('user-list-table', 'recentlySwitchStatus'),
Input('user-list-table', 'recentlySwitchRow')],
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')
else:
params = dict(user_id=int(recently_switch_row['key']), status='1', type='status')
edit_button_result = edit_user_api(params)
if edit_button_result['code'] == 200:
return [
{'type': 'switch-status'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('修改成功', type='success')
]
return [
{'type': 'switch-status'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('修改失败', type='error')
]
raise PreventUpdate
@app.callback(
[Output('user-delete-text', 'children'),
Output('user-delete-confirm-modal', 'visible'),
Output('user-delete-ids-store', 'data')],
[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')],
prevent_initial_call=True
)
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 == '删除'):
if trigger_id == {'index': 'delete', 'type': 'user-operation-button'}:
user_ids = ','.join(selected_row_keys)
else:
if recently_clicked_dropdown_item_title == '删除':
user_ids = recently_dropdown_item_clicked_row['key']
else:
raise PreventUpdate
return [
f'是否确认删除用户编号为{user_ids}的用户?',
True,
{'user_ids': user_ids}
]
raise PreventUpdate
@app.callback(
[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-delete-confirm-modal', 'okCounts'),
State('user-delete-ids-store', 'data'),
prevent_initial_call=True
)
def user_delete_confirm(delete_confirm, user_ids_data):
"""
删除用户弹窗确认回调,实现删除操作
"""
if delete_confirm:
params = user_ids_data
delete_button_info = delete_user_api(params)
if delete_button_info['code'] == 200:
return [
{'type': 'delete'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('删除成功', type='success')
]
return [
dash.no_update,
{'timestamp': time.time()},
fuc.FefferyFancyMessage('删除失败', type='error')
]
raise PreventUpdate
@app.callback(
[Output('user-reset-password-confirm-modal', 'visible'),
Output('reset-password-row-key-store', 'data'),
Output('reset-password-input', 'value')],
Input('user-list-table', 'nClicksDropdownItem'),
[State('user-list-table', 'recentlyClickedDropdownItemTitle'),
State('user-list-table', 'recentlyDropdownItemClickedRow')],
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:
raise PreventUpdate
return [
True,
{'user_id': user_id},
None
]
raise PreventUpdate
@app.callback(
[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-reset-password-confirm-modal', 'okCounts'),
[State('reset-password-row-key-store', 'data'),
State('reset-password-input', 'value')],
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
params = user_id_data
reset_button_info = reset_user_password_api(params)
if reset_button_info['code'] == 200:
return [
{'type': 'reset-password'},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('重置成功', type='success')
]
return [
dash.no_update,
{'timestamp': time.time()},
fuc.FefferyFancyMessage('重置失败', type='error')
]
raise PreventUpdate
@app.callback(
[Output('user_to_allocated_role-modal', 'visible'),
Output({'type': 'allocate_role-search', 'index': 'allocated'}, 'nClicks'),
Output('allocate_role-user_id-container', 'data')],
Input('user-list-table', 'nClicksDropdownItem'),
[State('user-list-table', 'recentlyClickedDropdownItemTitle'),
State('user-list-table', 'recentlyDropdownItemClickedRow'),
State({'type': 'allocate_role-search', 'index': 'allocated'}, 'nClicks')],
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 [
True,
allocated_role_search_nclick + 1 if allocated_role_search_nclick else 1,
recently_dropdown_item_clicked_row['key']
]
raise PreventUpdate
# 显示用户导入弹窗及重置上传弹窗组件状态回调
app.clientside_callback(
'''
(nClicks) => {
if (nClicks) {
return [
true,
[],
[],
false
];
}
return [
false,
window.dash_clientside.no_update,
window.dash_clientside.no_update,
window.dash_clientside.no_update
];
}
''',
[Output('user-import-confirm-modal', 'visible'),
Output('user-upload-choose', 'listUploadTaskRecord'),
Output('user-upload-choose', 'defaultFileList'),
Output('user-import-update-check', 'checked')],
Input('user-import', 'nClicks'),
prevent_initial_call=True
)
@app.callback(
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 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 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')
)
raise PreventUpdate
@app.callback(
[Output('user-export-container', 'data', allow_duplicate=True),
Output('user-export-complete-judge-container', 'data'),
Output('api-check-token', 'data', allow_duplicate=True),
Output('global-message-container', 'children', allow_duplicate=True)],
[Input('user-export', 'nClicks'),
Input('download-user-import-template', 'nClicks')],
prevent_initial_call=True
)
def export_user_list(export_click, download_click):
"""
导出用户信息回调
"""
trigger_id = dash.ctx.triggered_id
if export_click or download_click:
if trigger_id == 'user-export':
export_user_res = export_user_list_api({})
if export_user_res.status_code == 200:
export_user = export_user_res.content
return [
dcc.send_bytes(export_user, f'用户信息_{time.strftime("%Y%m%d%H%M%S", time.localtime())}.xlsx'),
{'timestamp': time.time()},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('导出成功', type='success')
]
return [
dash.no_update,
dash.no_update,
{'timestamp': time.time()},
fuc.FefferyFancyMessage('导出失败', type='error')
]
if trigger_id == 'download-user-import-template':
download_template_res = download_user_import_template_api()
if download_template_res.status_code == 200:
download_template = download_template_res.content
return [
dcc.send_bytes(download_template, f'用户导入模板_{time.strftime("%Y%m%d%H%M%S", time.localtime())}.xlsx'),
{'timestamp': time.time()},
{'timestamp': time.time()},
fuc.FefferyFancyMessage('下载成功', type='success')
]
return [
dash.no_update,
dash.no_update,
{'timestamp': time.time()},
fuc.FefferyFancyMessage('下载失败', type='error')
]
raise PreventUpdate
@app.callback(
Output('user-export-container', 'data', allow_duplicate=True),
Input('user-export-complete-judge-container', 'data'),
prevent_initial_call=True
)
def reset_user_export_status(data):
"""
导出完成后重置下载组件数据回调,防止重复下载文件
"""
time.sleep(0.5)
if data:
return None
raise PreventUpdate