Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/magic-dash-pro.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,20 @@ lambda current_user: current_user.user_name
> `DatabaseConfig.mysql_config`

当数据库类型为`'mysql'`时,配置**MySQL**数据库连接参数。


## 5 插件

### 快速添加页面

```cmd
python utils/add_page.py --name PagaName
```

| 参数名 | 类型 | 默认值 | 描述 |
|--------|------|--------|------|
| --name | str | 无 | 页面名称(必填)/key |
| --title | str | --name | 页面标题 |
| --describe | str | --name | 页面描述/注释 |
| --url | str | --name | 页面URL路径,默认/core/{--name} |
| --icon | str | "antd-menu" | 页面图标 |
18 changes: 18 additions & 0 deletions docs/magic-dash.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,21 @@ magic-dash
> `RouterConfig.wildcard_patterns`

基于正则表达式,配置应用中涉及到的通配页面模式字典。


## 5 插件

### 快速添加页面


```cmd
python utils/add_page.py --name PagaName
```

| 参数名 | 类型 | 默认值 | 描述 |
|--------|------|--------|------|
| --name | str | 无 | 页面名称(必填)/key |
| --title | str | --name | 页面标题 |
| --describe | str | --name | 页面描述/注释 |
| --url | str | --name | 页面URL路径,默认/core/{--name} |
| --icon | str | "antd-menu" | 页面图标 |
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@

app.clientside_callback(
# 控制核心页面侧边栏折叠
ClientsideFunction(
namespace="clientside_basic", function_name="handleSideCollapse"
),
ClientsideFunction(namespace="clientside_basic", function_name="handleSideCollapse"),
[
Output("core-side-menu-collapse-button-icon", "icon"),
Output("core-header-side", "style"),
Expand All @@ -45,17 +43,13 @@

app.clientside_callback(
# 控制页首页面搜索切换功能
ClientsideFunction(
namespace="clientside_basic", function_name="handleCorePageSearch"
),
ClientsideFunction(namespace="clientside_basic", function_name="handleCorePageSearch"),
Input("core-page-search", "value"),
)

app.clientside_callback(
# 控制ctrl+k快捷键聚焦页面搜索框
ClientsideFunction(
namespace="clientside_basic", function_name="handleCorePageSearchFocus"
),
ClientsideFunction(namespace="clientside_basic", function_name="handleCorePageSearchFocus"),
# 其中更新key用于强制刷新状态
[
Output("core-page-search", "autoFocus"),
Expand Down Expand Up @@ -182,6 +176,9 @@ def core_router(
# 更新页面返回内容
page_content = login_logs.render()

### ADD_PAGE 逻辑插入位置
### NEW_PAGE_TARGET

# 多标签页形式
if page_config.get("core_layout_type") == "tabs":
# 基于Patch进行标签页子项远程映射更新
Expand All @@ -200,8 +197,7 @@ def core_router(
"children": index.render(),
"closable": False,
"contextMenu": [
{"key": key, "label": key}
for key in ["关闭其他", "刷新页面"]
{"key": key, "label": key} for key in ["关闭其他", "刷新页面"]
],
}
)
Expand All @@ -214,8 +210,7 @@ def core_router(
"children": index.render(),
"closable": False,
"contextMenu": [
{"key": key, "label": key}
for key in ["关闭其他", "刷新页面"]
{"key": key, "label": key} for key in ["关闭其他", "刷新页面"]
],
},
{
Expand Down Expand Up @@ -302,9 +297,7 @@ def core_router(


app.clientside_callback(
ClientsideFunction(
namespace="clientside_basic", function_name="handleCoreTabsClose"
),
ClientsideFunction(namespace="clientside_basic", function_name="handleCoreTabsClose"),
[
Output("core-container", "items", allow_duplicate=True),
Output("core-container", "activeKey", allow_duplicate=True),
Expand All @@ -318,9 +311,7 @@ def core_router(
)

app.clientside_callback(
ClientsideFunction(
namespace="clientside_basic", function_name="handleCoreFullscreenToggle"
),
ClientsideFunction(namespace="clientside_basic", function_name="handleCoreFullscreenToggle"),
[
Output("core-fullscreen", "isFullscreen"),
Output("core-full-screen-toggle-button-icon", "icon"),
Expand Down
207 changes: 188 additions & 19 deletions magic_dash/templates/magic-dash-pro/components/user_manage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import uuid
import time
import dash
from dash import set_props
import feffery_antd_components as fac
Expand All @@ -11,6 +9,11 @@
from models.users import Users
from configs import AuthConfig

import uuid
import time
import secrets
import string


def render():
"""渲染用户管理抽屉"""
Expand Down Expand Up @@ -38,12 +41,20 @@ def refresh_user_manage_table_data():
"gold" if item["user_role"] == AuthConfig.admin_role else "blue"
),
},
"操作": {
"content": "删除",
"type": "link",
"danger": True,
"disabled": item["user_role"] == AuthConfig.admin_role,
},
"操作": [
{
"content": "删除",
"type": "link",
"danger": True,
"disabled": item["user_role"] == AuthConfig.admin_role,
},
{
"content": "重置密码",
"type": "link",
"danger": False,
"disabled": item["user_role"] == AuthConfig.admin_role,
},
],
}
for item in all_users
]
Expand Down Expand Up @@ -75,6 +86,26 @@ def render_user_manage_drawer(visible):
renderFooter=True,
okClickClose=False,
),
# 删除用户模态框
fac.AntdModal(
id="user-manage-delete-user-modal",
title=fac.AntdSpace(
[fac.AntdIcon(icon="antd-user-delete"), "删除用户"]
),
mask=False,
renderFooter=True,
okClickClose=False,
visible=False,
),
fac.AntdModal(
id="user-manage-reset-password-modal",
title=fac.AntdSpace(
[fac.AntdIcon(icon="antd-key"), "重置密码"]),
mask=False,
renderFooter=True,
okClickClose=False,
visible=False,
),
fac.AntdSpace(
[
fac.AntdTable(
Expand Down Expand Up @@ -249,6 +280,7 @@ def handle_add_user(okCounts, values):
user_role=values["user-manage-add-user-form-user-role"],
)

# 提示
set_props(
"global-message",
{
Expand All @@ -258,6 +290,11 @@ def handle_add_user(okCounts, values):
)
},
)
# 关闭modal
set_props(
"user-manage-add-user-modal",
{"visible": False},
)

# 刷新用户列表
set_props(
Expand All @@ -266,6 +303,7 @@ def handle_add_user(okCounts, values):
)


# 表格栏目高级操作
@app.callback(
Input("user-manage-table", "nClicksButton"),
[
Expand All @@ -274,20 +312,31 @@ def handle_add_user(okCounts, values):
],
prevent_initial_call=True,
)
def handle_user_delete(nClicksButton, clickedContent, recentlyButtonClickedRow):
"""处理用户删除逻辑"""

def advanced_user_operation(nClicksButton, clickedContent, recentlyButtonClickedRow):
"""
处理表格栏高级操作逻辑
"""
# 处理删除逻辑
if clickedContent == "删除":
# 删除用户
Users.delete_user(user_id=recentlyButtonClickedRow["user_id"])

set_props(
"global-message",
"user-manage-delete-user-modal",
{
"children": fac.AntdMessage(
type="success",
content="用户删除成功",
)
"visible": True,
"children": fac.AntdSpace(
[
fac.AntdAlert(
message=f"是否删除用户{recentlyButtonClickedRow['user_name']}"
),
fac.AntdAlert(
message="该操作不可逆",
type="warning",
showIcon=True,
),
],
direction="vertical",
size="middle",
style={"width": "100%"},
),
},
)

Expand All @@ -296,3 +345,123 @@ def handle_user_delete(nClicksButton, clickedContent, recentlyButtonClickedRow):
"user-manage-table",
{"data": refresh_user_manage_table_data()},
)
elif clickedContent == "重置密码":
set_props(
"user-manage-reset-password-modal",
{
"visible": True,
"children": fac.AntdSpace(
[
fac.AntdAlert(
message=f"是否重置用户{recentlyButtonClickedRow['user_name']}密码"
),
fac.AntdAlert(
message="该操作不可逆",
type="warning",
showIcon=True,
),
],
direction="vertical",
size="middle",
style={"width": "100%"},
),
},
)
# 重置密码
elif clickedContent == "重置密码":
set_props(
"user-manage-reset-password-modal",
{
"visible": True,
"children": fac.AntdSpace(
[
fac.AntdAlert(
message=f"是否重置用户{recentlyButtonClickedRow['user_name']}密码"
),
fac.AntdAlert(
message="该操作不可逆",
type="warning",
showIcon=True,
),
],
direction="vertical",
size="middle",
style={"width": "100%"},
),
},
)


@app.callback(
Input("user-manage-delete-user-modal", "okCounts"),
State("user-manage-table", "recentlyButtonClickedRow"),
prevent_initial_call=True,
)
def handle_user_delete(okCounts, recentlyButtonClickedRow):
"""模态框处理用户删除逻辑"""
# 删除用户
Users.delete_user(user_id=recentlyButtonClickedRow["user_id"])

set_props(
"global-message",
{
"children": fac.AntdMessage(
type="success",
content="用户删除成功",
)
},
)
time.sleep(0.5)
set_props(
"user-manage-delete-user-modal",
{"visible": False},
)

# 刷新用户列表
set_props(
"user-manage-table",
{"data": refresh_user_manage_table_data()},
)


@app.callback(
Input("user-manage-reset-password-modal", "okCounts"),
State("user-manage-table", "recentlyButtonClickedRow"),
prevent_initial_call=True,
)
def handle_user_reset_password(okCounts, recentlyButtonClickedRow):
"""模态框处理用户重置密码逻辑"""

# 定义密码字符集
characters = string.ascii_letters + string.digits + "!@#$%^&*"
# 生成 12 位随机密码
new_password = "".join(secrets.choice(characters) for _ in range(8))

Users.update_user(
user_id=recentlyButtonClickedRow["user_id"],
password_hash=generate_password_hash(new_password),
)
# 重置密码
set_props(
"global-message",
{
"children": [
fac.AntdMessage(
type="success",
content=f"用户{recentlyButtonClickedRow['user_name']}密码重置为 {new_password}",
),
]
},
)

time.sleep(0.5)
set_props(
"user-manage-reset-password-modal",
{"visible": False},
)

# 刷新用户列表
set_props(
"user-manage-table",
{"data": refresh_user_manage_table_data()},
)
Loading