diff --git a/README.md b/README.md
index 9c8b8dbcd98972e6a1cdb36d1460ef867d851394..04caeaf93172d3348f20f14339521216b4f0e728 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,14 @@
-Dash-FastAPI-Admin v1.0.2
+Dash-FastAPI-Admin v1.0.4
基于Dash+FastAPI前后端分离的纯Python快速开发框架
-
+
+
+
## 平台简介
@@ -85,7 +87,7 @@ Dash-FastAPI-Admin是一套全部开源的快速开发平台,毫无保留给
git clone https://gitee.com/insistence2022/dash-fastapi-admin.git
# 进入项目根目录
-cd Dash-FastAPI-Admin
+cd dash-fastapi-admin
# 安装项目依赖环境
pip3 install -r requirements.txt
diff --git a/dash-fastapi-backend/module_admin/controller/login_controller.py b/dash-fastapi-backend/module_admin/controller/login_controller.py
index 3a88f9d2ae9619b676933a9a7e43a6655b3ed36e..686b9d6e72108da3bd240a7fd0651a251a253fb8 100644
--- a/dash-fastapi-backend/module_admin/controller/login_controller.py
+++ b/dash-fastapi-backend/module_admin/controller/login_controller.py
@@ -47,8 +47,8 @@ async def login(request: Request, form_data: CustomOAuth2PasswordRequestForm = D
await request.app.state.redis.set(f'access_token:{session_id}', access_token,
ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES))
# 此方法可实现同一账号同一时间只能登录一次
- # await request.app.state.redis.set(f'{result.user_id}_access_token', access_token, ex=timedelta(minutes=30))
- # await request.app.state.redis.set(f'{result.user_id}_session_id', session_id, ex=timedelta(minutes=30))
+ # await request.app.state.redis.set(f'access_token:{result[0].user_id}', access_token,
+ # ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES))
logger.info('登录成功')
# 判断请求是否来自于api文档,如果是返回指定格式的结果,用于修复api文档认证成功后token显示undefined的bug
request_from_swagger = request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False
diff --git a/dash-fastapi-backend/module_admin/service/login_service.py b/dash-fastapi-backend/module_admin/service/login_service.py
index f6b54a0b0bb1fe283af8f159a03c22bef95e9067..91eda4f9e85a0ca6c0dd1c2952c14e29336d8966 100644
--- a/dash-fastapi-backend/module_admin/service/login_service.py
+++ b/dash-fastapi-backend/module_admin/service/login_service.py
@@ -75,15 +75,12 @@ async def get_current_user(request: Request = Request, token: str = Depends(oaut
raise AuthException(data="", message="用户token不合法")
redis_token = await request.app.state.redis.get(f'access_token:{session_id}')
# 此方法可实现同一账号同一时间只能登录一次
- # redis_token = await request.app.state.redis.get(f'{user.user_basic_info[0].user_id}_access_token')
- # redis_session = await request.app.state.redis.get(f'{user.user_basic_info[0].user_id}_session_id')
+ # redis_token = await request.app.state.redis.get(f'access_token:{user.user_basic_info[0].user_id}')
if token == redis_token:
await request.app.state.redis.set(f'access_token:{session_id}', redis_token,
ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES))
- # await request.app.state.redis.set(f'{user.user_basic_info[0].user_id}_access_token', redis_token,
- # ex=timedelta(minutes=30))
- # await request.app.state.redis.set(f'{user.user_basic_info[0].user_id}_session_id', redis_session,
- # ex=timedelta(minutes=30))
+ # await request.app.state.redis.set(f'access_token:{user.user_basic_info[0].user_id}', redis_token,
+ # ex=timedelta(minutes=JwtConfig.REDIS_TOKEN_EXPIRE_MINUTES))
return CurrentUserInfoServiceResponse(
user=user.user_basic_info[0],
diff --git a/dash-fastapi-backend/sql/dash-fastapi.sql b/dash-fastapi-backend/sql/dash-fastapi.sql
index 8b2657b730c0de3f5a3a4b4a6495956658330159..3a541bdf18e608331718df457e547d3b4f4181e2 100644
--- a/dash-fastapi-backend/sql/dash-fastapi.sql
+++ b/dash-fastapi-backend/sql/dash-fastapi.sql
@@ -260,9 +260,9 @@ CREATE TABLE `sys_job` (
-- ----------------------------
-- Records of sys_job
-- ----------------------------
-INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'default', 'default', 'module_task.scheduler_test.job', 'test', NULL, '0/10 * * * * ?', '2', '0', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
-INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'sqlalchemy', 'default', 'module_task.scheduler_test.job', 'new', '{\"test\": 111}', '0/15 * * * * ?', '1', '1', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
-INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'redis', 'default', 'module_task.scheduler_test.job', NULL, NULL, '0/20 * * * * ?', '3', '1', '1', 'admin', '2023-05-23 16:13:34', '', NULL, '');
+INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'default', 'default', 'module_task.scheduler_test.job', 'test', NULL, '0/10 * * * * *', '2', '0', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
+INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'sqlalchemy', 'default', 'module_task.scheduler_test.job', 'new', '{\"test\": 111}', '0/15 * * * * *', '1', '1', '1', 'admin', '2023-05-23 16:13:34', 'admin', '2023-05-23 16:13:34', '');
+INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'redis', 'default', 'module_task.scheduler_test.job', NULL, NULL, '0/20 * * * * *', '3', '1', '1', 'admin', '2023-05-23 16:13:34', '', NULL, '');
-- ----------------------------
-- Table structure for sys_job_log
diff --git a/dash-fastapi-backend/utils/common_util.py b/dash-fastapi-backend/utils/common_util.py
index a58f9895f819181f9f425497182845739df9663d..1cf60f608d6989dc20de497bf53b46c3732c8e26 100644
--- a/dash-fastapi-backend/utils/common_util.py
+++ b/dash-fastapi-backend/utils/common_util.py
@@ -5,6 +5,7 @@ from openpyxl import Workbook
from openpyxl.styles import Alignment, PatternFill
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.datavalidation import DataValidation
+from typing import List
from config.env import CachePathConfig
@@ -59,7 +60,7 @@ def bytes2file_response(bytes_info):
yield bytes_info
-def export_list2excel(list_data: list):
+def export_list2excel(list_data: List):
"""
工具方法:将需要导出的list数据转化为对应excel的二进制数据
:param list_data: 数据列表
@@ -73,7 +74,7 @@ def export_list2excel(list_data: list):
return binary_data
-def get_excel_template(header_list: list, selector_header_list: list, option_list: list[dict]):
+def get_excel_template(header_list: List, selector_header_list: List, option_list: List[dict]):
"""
工具方法:将需要导出的list数据转化为对应excel的二进制数据
:param header_list: 表头数据列表
diff --git a/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py b/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
index 2ec0ffd36ffdb2b65eabb5bf8d3712c52afe0914..754ed98a6af7f6260c35d8e391ccc87659bad48b 100644
--- a/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
+++ b/dash-fastapi-frontend/callbacks/monitor_c/logininfor_c.py
@@ -171,7 +171,7 @@ def login_log_delete_modal(operation_click, selected_row_keys):
info_ids = ','.join(selected_row_keys)
return [
- f'是否确认删除访问编号为{info_ids}的操作日志?',
+ f'是否确认删除访问编号为{info_ids}的登录日志?',
True,
{'oper_type': 'delete', 'info_ids': info_ids}
]
diff --git a/dash-fastapi-frontend/views/__init__.py b/dash-fastapi-frontend/views/__init__.py
index 5443387b773ba80912da349347e71ee486851525..bc382401e0e24f3e75582fe162ccc540b34e4d86 100644
--- a/dash-fastapi-frontend/views/__init__.py
+++ b/dash-fastapi-frontend/views/__init__.py
@@ -1,5 +1,6 @@
from . import (
layout,
+ dashboard,
system,
monitor,
tool,
diff --git a/dash-fastapi-frontend/views/dashboard/__init__.py b/dash-fastapi-frontend/views/dashboard/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..da12fc7b497318324bfd0da23de8a85f84fb8994
--- /dev/null
+++ b/dash-fastapi-frontend/views/dashboard/__init__.py
@@ -0,0 +1,8 @@
+from .components import page_top, page_bottom
+
+
+def render_dashboard():
+ return [
+ page_top.render_page_top(),
+ page_bottom.render_page_bottom()
+ ]
diff --git a/dash-fastapi-frontend/views/dashboard/components/page_bottom.py b/dash-fastapi-frontend/views/dashboard/components/page_bottom.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5a94c48a6b6a51f6b5fbad8b224032beff5c944
--- /dev/null
+++ b/dash-fastapi-frontend/views/dashboard/components/page_bottom.py
@@ -0,0 +1,533 @@
+from dash import html
+import feffery_antd_components as fac
+import feffery_utils_components as fuc
+import feffery_antd_charts as fact
+
+
+def render_page_bottom():
+ # 模拟数据
+ radar_origin_data = [
+ {
+ 'name': '个人',
+ 'ref': 10,
+ 'koubei': 8,
+ 'output': 4,
+ 'contribute': 5,
+ 'hot': 7
+ },
+ {
+ 'name': '团队',
+ 'ref': 3,
+ 'koubei': 9,
+ 'output': 6,
+ 'contribute': 3,
+ 'hot': 1
+ },
+ {
+ 'name': '部门',
+ 'ref': 4,
+ 'koubei': 1,
+ 'output': 6,
+ 'contribute': 5,
+ 'hot': 7
+ }
+ ]
+
+ radar_data = []
+ radar_title_map = {
+ 'ref': '引用',
+ 'koubei': '口碑',
+ 'output': '产量',
+ 'contribute': '贡献',
+ 'hot': '热度'
+ }
+
+ for item in radar_origin_data:
+ for key, value in item.items():
+ if key != 'name':
+ radar_data.append({
+ 'name': item['name'],
+ 'label': radar_title_map[key],
+ 'value': value
+ })
+
+ project_list = [
+ {
+ "id": "xxx1",
+ "title": "Alipay",
+ "logo": "https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png",
+ "description": "那是一种内在的东西,他们到达不了,也无法触及的",
+ "updatedAt": "2023-09-15T01:08:36.135Z",
+ "member": "科学搬砖组",
+ "href": "",
+ "memberLink": ""
+ },
+ {
+ "id": "xxx2",
+ "title": "Angular",
+ "logo": "https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png",
+ "description": "希望是一个好东西,也许是最好的,好东西是不会消亡的",
+ "updatedAt": "2017-07-24T00:00:00.000Z",
+ "member": "全组都是吴彦祖",
+ "href": "",
+ "memberLink": ""
+ },
+ {
+ "id": "xxx3",
+ "title": "Ant Design",
+ "logo": "https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png",
+ "description": "城镇中有那么多的酒馆,她却偏偏走进了我的酒馆",
+ "updatedAt": "2023-09-15T01:08:36.135Z",
+ "member": "中二少女团",
+ "href": "",
+ "memberLink": ""
+ },
+ {
+ "id": "xxx4",
+ "title": "Ant Design Pro",
+ "logo": "https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png",
+ "description": "那时候我只会想自己想要什么,从不想自己拥有什么",
+ "updatedAt": "2017-07-23T00:00:00.000Z",
+ "member": "程序员日常",
+ "href": "",
+ "memberLink": ""
+ },
+ {
+ "id": "xxx5",
+ "title": "Bootstrap",
+ "logo": "https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png",
+ "description": "凛冬将至",
+ "updatedAt": "2017-07-23T00:00:00.000Z",
+ "member": "高逼格设计天团",
+ "href": "",
+ "memberLink": ""
+ },
+ {
+ "id": "xxx6",
+ "title": "React",
+ "logo": "https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png",
+ "description": "生命就像一盒巧克力,结果往往出人意料",
+ "updatedAt": "2017-07-23T00:00:00.000Z",
+ "member": "骗你来学计算机",
+ "href": "",
+ "memberLink": ""
+ }
+ ]
+
+ activity_list = [
+ {
+ "id": "trend-1",
+ "updatedAt": "2023-09-15 01:08:36",
+ "user": {
+ "name": "曲丽丽",
+ "avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png"
+ },
+ "group": {
+ "name": "高逼格设计天团",
+ "link": "http://github.com/"
+ },
+ "project": {
+ "name": "六月迭代",
+ "link": "http://github.com/"
+ },
+ "template": "新建项目"
+ },
+ {
+ "id": "trend-2",
+ "updatedAt": "2023-09-15 01:08:36",
+ "user": {
+ "name": "付小小",
+ "avatar": "https://gw.alipayobjects.com/zos/rmsportal/cnrhVkzwxjPwAaCfPbdc.png"
+ },
+ "group": {
+ "name": "高逼格设计天团",
+ "link": "http://github.com/"
+ },
+ "project": {
+ "name": "六月迭代",
+ "link": "http://github.com/"
+ },
+ "template": "新建项目"
+ },
+ {
+ "id": "trend-3",
+ "updatedAt": "2023-09-15 01:08:36",
+ "user": {
+ "name": "林东东",
+ "avatar": "https://gw.alipayobjects.com/zos/rmsportal/gaOngJwsRYRaVAuXXcmB.png"
+ },
+ "group": {
+ "name": "中二少女团",
+ "link": "http://github.com/"
+ },
+ "project": {
+ "name": "六月迭代",
+ "link": "http://github.com/"
+ },
+ "template": "新建项目"
+ },
+ {
+ "id": "trend-4",
+ "updatedAt": "2023-09-15 01:08:36",
+ "user": {
+ "name": "周星星",
+ "avatar": "https://gw.alipayobjects.com/zos/rmsportal/WhxKECPNujWoWEFNdnJE.png"
+ },
+ "group": {
+ "name": "白鹭酱油开发组",
+ "link": "http://github.com/"
+ },
+ "project": {
+ "name": "5 月日常迭代",
+ "link": "http://github.com/"
+ },
+ "template": "发布了"
+ },
+ {
+ "id": "trend-5",
+ "updatedAt": "2023-09-15 01:08:36",
+ "user": {
+ "name": "乐哥",
+ "avatar": "https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png"
+ },
+ "group": {
+ "name": "程序员日常",
+ "link": "http://github.com/"
+ },
+ "project": {
+ "name": "品牌迭代",
+ "link": "http://github.com/"
+ },
+ "template": "新建项目"
+ }
+ ]
+
+ return html.Div(
+ [
+ fac.AntdRow(
+ [
+ fac.AntdCol(
+ [
+ fac.AntdCard(
+ [
+ fac.AntdCardGrid(
+ [
+ html.Div(
+ [
+ fac.AntdAvatar(
+ mode='image',
+ src=item.get('logo'),
+ size='small'
+ ),
+ html.A(
+ item.get('title')
+ )
+ ],
+ className='card-title'
+ ),
+ html.Div(
+ item.get('description'),
+ className='card-description'
+ ),
+ html.Div(
+ [
+ html.A(item.get('member')),
+ html.Span(
+ '9小时前',
+ className='datetime'
+ )
+ ],
+ className='project-item'
+ )
+ ]
+ )
+ for item in project_list
+ ],
+ className='project-list',
+ title='进行中的项目',
+ bordered=False,
+ extraLink={
+ 'content': '全部项目'
+ },
+ bodyStyle={
+ 'padding': 0
+ },
+ style={
+ 'marginBottom': '24px',
+ 'boxShadow': 'rgba(0, 0, 0, 0.1) 0px 4px 12px'
+ }
+ ),
+ fac.AntdCard(
+ fac.AntdSpace(
+ [
+ html.Div(
+ [
+ html.Div(
+ [
+ html.Div(
+ fac.AntdAvatar(
+ mode='image',
+ src=item.get('user').get('avatar'),
+ size='small',
+ ),
+ style={
+ 'flex': '0 1',
+ 'marginRight': '16px'
+ }
+ ),
+ html.Div(
+ [
+ html.Div(
+ [
+ html.Span(f"{item.get('user').get('name')} 在 "),
+ html.A(item.get('group').get('name'), href=item.get('group').get('link')),
+ html.Span(f" {item.get('template')} "),
+ html.A(item.get('project').get('name'), href=item.get('project').get('link'))
+ ],
+ key=item.get('id')
+ ),
+ html.Div(
+ item.get('updatedAt'),
+ style={
+ 'color': 'rgba(0,0,0,.45)',
+ 'fontSize': '14px',
+ 'lineHeight': '22px'
+ }
+ ),
+ ],
+ style={
+ 'flex': '1 1 auto'
+ }
+ ),
+ ],
+ style={
+ 'display': 'flex'
+ }
+ ),
+ fac.AntdDivider()
+ ]
+ )
+ for item in activity_list
+ ],
+ direction='vertical',
+ style={
+ 'width': '100%',
+ 'maxHeight': '500px',
+ 'overflowY': 'auto'
+ }
+ ),
+ title='动态',
+ bordered=False,
+ style={
+ 'marginBottom': '24px',
+ 'boxShadow': 'rgba(0, 0, 0, 0.1) 0px 4px 12px'
+ }
+ ),
+ ],
+ xl=16,
+ lg=24,
+ md=24,
+ sm=24,
+ xs=24
+ ),
+ fac.AntdCol(
+ [
+ fac.AntdCard(
+ html.Div(
+ [
+ html.A('操作一'),
+ html.A('操作二'),
+ html.A('操作三'),
+ html.A('操作四'),
+ html.A('操作五'),
+ fac.AntdButton(
+ '添加',
+ type="primary",
+ size='small',
+ icon=fac.AntdIcon(icon='antd-plus'),
+ style={
+ 'marginLeft': '20px'
+ }
+ )
+ ],
+ className='item-group'
+ ),
+ title='快速开始 / 便捷导航',
+ bordered=False,
+ style={
+ 'marginBottom': '24px',
+ 'boxShadow': 'rgba(0, 0, 0, 0.1) 0px 4px 12px'
+ }
+ ),
+ fac.AntdCard(
+ html.Div(
+ fact.AntdRadar(
+ height=343,
+ data=radar_data,
+ xField='label',
+ yField='value',
+ seriesField='name',
+ point={},
+ legend={
+ 'position': 'bottom'
+ },
+ ),
+ style={
+ 'minHeight': '400px',
+ 'margin': '0 auto',
+ 'paddingTop': '30px'
+ }
+ ),
+ title='XX 指数',
+ bordered=False,
+ bodyStyle={
+ 'padding': 0
+ },
+ style={
+ 'marginBottom': '24px',
+ 'boxShadow': 'rgba(0, 0, 0, 0.1) 0px 4px 12px'
+ }
+ ),
+ fac.AntdCard(
+ html.Div(
+ fac.AntdRow(
+ [
+ fac.AntdCol(
+ html.A(
+ [
+ fac.AntdAvatar(
+ mode='image',
+ src=item.get('logo'),
+ size='small'
+ ),
+ html.Span(
+ item.get('member'),
+ className='member'
+ )
+ ]
+ ),
+ span=12
+ )
+ for item in project_list
+ ]
+ ),
+ className='members'
+ ),
+ title='团队',
+ bordered=False,
+ style={
+ 'marginBottom': '24px',
+ 'boxShadow': 'rgba(0, 0, 0, 0.1) 0px 4px 12px'
+ }
+ ),
+ ],
+ xl=8,
+ lg=24,
+ md=24,
+ sm=24,
+ xs=24,
+ style={
+ 'padding': '0 12px'
+ }
+ ),
+ ],
+ gutter=24
+ ),
+ fuc.FefferyStyle(
+ rawStyle='''
+ .project-list .card-title {
+ font-size: 0;
+ }
+
+ .project-list .card-title a {
+ color: rgba(0, 0, 0, 0.85);
+ margin-left: 12px;
+ line-height: 24px;
+ height: 24px;
+ display: inline-block;
+ vertical-align: top;
+ font-size: 14px;
+ }
+
+ .project-list .card-title a:hover {
+ color: #1890ff;
+ }
+
+ .project-list .card-description {
+ color: rgba(0, 0, 0, 0.45);
+ height: 44px;
+ line-height: 22px;
+ overflow: hidden;
+ }
+
+ .project-list .project-item {
+ display: flex;
+ margin-top: 8px;
+ overflow: hidden;
+ font-size: 12px;
+ height: 20px;
+ line-height: 20px;
+ }
+
+ .project-list .project-item a {
+ color: rgba(0, 0, 0, 0.45);
+ display: inline-block;
+ flex: 1 1 0;
+ }
+
+ .project-list .project-item a:hover {
+ color: #1890ff;
+ }
+
+ .project-list .project-item .datetime {
+ color: rgba(0, 0, 0, 0.25);
+ flex: 0 0 auto;
+ float: right;
+ }
+
+ .project-list .ant-card-meta-description {
+ color: rgba(0, 0, 0, 0.45);
+ height: 44px;
+ line-height: 22px;
+ overflow: hidden;
+ }
+
+ .item-group {
+ padding: 20px 0 8px 24px;
+ font-size: 0;
+ }
+
+ .item-group a {
+ color: rgba(0, 0, 0, 0.65);
+ display: inline-block;
+ font-size: 14px;
+ margin-bottom: 13px;
+ width: 25%;
+ padding-left: 20px;
+ }
+
+ .members a {
+ display: block;
+ margin: 12px 0;
+ line-height: 24px;
+ height: 24px;
+ }
+
+ .members a .member {
+ font-size: 14px;
+ color: rgba(0, 0, 0, 0.65);
+ line-height: 24px;
+ max-width: 100px;
+ vertical-align: top;
+ margin-left: 12px;
+ transition: all 0.3s;
+ display: inline-block;
+ }
+
+ .members a .member:hover span {
+ color: #1890ff;
+ }
+ '''
+ )
+ ]
+ )
diff --git a/dash-fastapi-frontend/views/dashboard/components/page_top.py b/dash-fastapi-frontend/views/dashboard/components/page_top.py
new file mode 100644
index 0000000000000000000000000000000000000000..dff95c995ad9cab9dc4700c086569aac025cfdf9
--- /dev/null
+++ b/dash-fastapi-frontend/views/dashboard/components/page_top.py
@@ -0,0 +1,148 @@
+from dash import html
+import feffery_antd_components as fac
+import feffery_utils_components as fuc
+
+from flask import session
+
+
+def render_page_top():
+
+ return html.Div(
+ [
+ html.Div(
+ fac.AntdAvatar(
+ id='dashboard-avatar-info',
+ mode='image',
+ src=session.get('user_info').get('avatar'),
+ size='large'
+ ),
+ className='avatar',
+ ),
+ html.Div(
+ [
+ html.Div(
+ fac.AntdText(f"早安,{session.get('user_info').get('nick_name')},祝你开心每一天!"),
+ className='content-title',
+ ),
+ html.Div('交互专家 |蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED')
+ ],
+ className='content',
+ ),
+ html.Div(
+ [
+ html.Div(
+ fac.AntdStatistic(
+ title='项目数',
+ value=56
+ ),
+ className='stat-item'
+ ),
+ html.Div(
+ fac.AntdStatistic(
+ title='团队内排名',
+ value=8,
+ suffix='/ 24'
+ ),
+ className='stat-item'
+ ),
+ html.Div(
+ fac.AntdStatistic(
+ title='项目访问',
+ value=2223
+ ),
+ className='stat-item'
+ ),
+ ],
+ className='extra-content'
+ ),
+ fuc.FefferyStyle(
+ rawStyle='''
+ .page-header-content {
+ display: flex;
+ }
+
+ .page-header-content .avatar {
+ flex: 0 1 72px;
+ }
+
+ .page-header-content .avatar > span {
+ display: block;
+ width: 72px;
+ height: 72px;
+ border-radius: 72px;
+ }
+
+ .page-header-content .content {
+ position: relative;
+ top: 4px;
+ margin-left: 24px;
+ line-height: 22px;
+ color: rgba(0,0,0,.45);
+ flex: 1 1 auto;
+ }
+
+ .page-header-content .content .content-title {
+ margin-bottom: 12px;
+ font-size: 20px;
+ font-weight: 500;
+ line-height: 28px;
+ color: rgba(0,0,0,.85);
+ }
+
+ .extra-content {
+ float: right;
+ white-space: nowrap;
+ }
+
+ .extra-content .stat-item {
+ position: relative;
+ display: inline-block;
+ padding: 0 32px;
+ }
+
+ .extra-content .stat-item > p:first-child {
+ margin-bottom: 4px;
+ font-size: 14px;
+ line-height: 22px;
+ color: rgba(0,0,0,.45);
+ }
+
+ .extra-content .stat-item > p {
+ margin: 0;
+ font-size: 30px;
+ line-height: 38px;
+ color: rgba(0,0,0,.85);
+ }
+
+ .extra-content .stat-item > p > span {
+ font-size: 20px;
+ color: rgba(0,0,0,.45);
+ }
+
+ .extra-content .stat-item::after {
+ position: absolute;
+ top: 8px;
+ right: 0;
+ width: 1px;
+ height: 40px;
+ background-color: #e8e8e8;
+ content: '';
+ }
+
+ .extra-content .stat-item:last-child {
+ padding-right: 0;
+ }
+
+ .extra-content .stat-item:last-child::after {
+ display: none;
+ }
+ '''
+ )
+ ],
+ className='page-header-content',
+ style={
+ 'padding': '12px',
+ 'marginBottom': '24px',
+ 'boxShadow': 'rgba(0, 0, 0, 0.1) 0px 4px 12px'
+ }
+ )
diff --git a/dash-fastapi-frontend/views/layout/__init__.py b/dash-fastapi-frontend/views/layout/__init__.py
index 88f9f2dc33af5d53ea4de534886e41aca057351a..52b992ba21719b0b4fd802100718a846c9f453c1 100644
--- a/dash-fastapi-frontend/views/layout/__init__.py
+++ b/dash-fastapi-frontend/views/layout/__init__.py
@@ -19,20 +19,6 @@ def render_content(menu_info):
html.Div(id='idle-placeholder-container'),
- # 注入相关modal
- # html.Div(
- # [
- # # 个人资料面板
- # fac.AntdModal(
- # render_user_profile(),
- # id='index-personal-info-modal',
- # title='个人资料',
- # width=1000,
- # mask=False
- # )
- # ]
- # ),
-
# 布局设置抽屉
fac.AntdDrawer(
[
diff --git a/dash-fastapi-frontend/views/layout/components/content.py b/dash-fastapi-frontend/views/layout/components/content.py
index 7d17211edb86f8ba8dd5e3433a56545cd8bde4ee..454dbd85b147d9287a63aab58ef062f70d919b9e 100644
--- a/dash-fastapi-frontend/views/layout/components/content.py
+++ b/dash-fastapi-frontend/views/layout/components/content.py
@@ -1,6 +1,8 @@
from dash import html
import feffery_antd_components as fac
+from views.dashboard import render_dashboard
+
def render_main_content():
return [
@@ -14,11 +16,7 @@ def render_main_content():
'label': '首页',
'key': '首页',
'closable': False,
- 'children': fac.AntdAlert(
- type='info',
- showIcon=True,
- message='这里是主标签页,通常建议设置为不可关闭并展示一些总览类型的信息'
- )
+ 'children': render_dashboard()
}
],
id='tabs-container',
diff --git a/dash-fastapi-frontend/views/system/user/__init__.py b/dash-fastapi-frontend/views/system/user/__init__.py
index fc81c65da071e13146d44f5978866a346be3c346..498ba1637c887d0f71fcc6fae4e02234b0cbf88c 100644
--- a/dash-fastapi-frontend/views/system/user/__init__.py
+++ b/dash-fastapi-frontend/views/system/user/__init__.py
@@ -633,7 +633,7 @@ def render(button_perms):
'width': 200
}
),
- label='岗位',
+ label='角色',
id='user-add-role-form-item',
labelCol={
'offset': 8