| @@ -20,16 +20,16 @@ export default { | |||
| // localhost:8000/api/** -> https://preview.pro.ant.design/api/** | |||
| '/api/': { | |||
| // 要代理的地址 | |||
| // target: 'http://172.20.32.181:31205', | |||
| target: 'http://172.20.32.98:8082', | |||
| target: 'http://172.20.32.181:31213', // 开发环境 | |||
| // target: 'http://172.20.32.98:8082', | |||
| // target: 'http://172.20.32.150:8082', | |||
| // 配置了这个可以从 http 代理到 https | |||
| // 依赖 origin 的功能可能需要这个,比如 cookie | |||
| changeOrigin: true, | |||
| pathRewrite: { '^/api': '' }, | |||
| // pathRewrite: { '^/api': '' }, | |||
| }, | |||
| '/profile/avatar/': { | |||
| target: 'http://172.20.32.181:31205', | |||
| target: 'http://172.20.32.181:31213', | |||
| changeOrigin: true, | |||
| }, | |||
| }, | |||
| @@ -14,10 +14,9 @@ export default [ | |||
| { | |||
| path: '/', | |||
| redirect: '/workspace', | |||
| breadcrumb: '工作空间', | |||
| }, | |||
| { | |||
| name: 'workspace', | |||
| name: '工作空间', | |||
| path: '/workspace', | |||
| routes: [ | |||
| { | |||
| @@ -41,6 +40,7 @@ export default [ | |||
| }, | |||
| { | |||
| path: '/account', | |||
| name: '用户中心', | |||
| routes: [ | |||
| { | |||
| name: '用户中心', | |||
| @@ -70,7 +70,7 @@ export default [ | |||
| ], | |||
| }, | |||
| { | |||
| name: 'developmentEnvironment', | |||
| name: '开发环境', | |||
| path: '/developmentEnvironment', | |||
| routes: [ | |||
| { | |||
| @@ -79,12 +79,12 @@ export default [ | |||
| component: './DevelopmentEnvironment/Editor', | |||
| }, | |||
| { | |||
| name: '创建编辑器', | |||
| name: '创建开发环境', | |||
| path: 'create', | |||
| component: './DevelopmentEnvironment/Create', | |||
| }, | |||
| { | |||
| name: '编辑器', | |||
| name: '开发环境详情', | |||
| path: 'editor', | |||
| component: './DevelopmentEnvironment/Editor', | |||
| }, | |||
| @@ -229,7 +229,7 @@ export default [ | |||
| name: '应用开发', | |||
| path: '', | |||
| key: 'appsDeployment', | |||
| component: './missingPage.jsx', | |||
| component: './Application', | |||
| }, | |||
| ], | |||
| }, | |||
| @@ -306,47 +306,47 @@ export default [ | |||
| }, | |||
| { | |||
| name: '用户管理', | |||
| path: '/system/user', | |||
| path: 'user', | |||
| component: './System/User', | |||
| }, | |||
| { | |||
| name: '角色管理', | |||
| path: '/system/role', | |||
| path: 'role', | |||
| component: './System/Role', | |||
| }, | |||
| { | |||
| name: '定时任务', | |||
| path: '/system/job', | |||
| path: 'job', | |||
| component: './Monitor/Job', | |||
| }, | |||
| { | |||
| name: '菜单管理', | |||
| path: '/system/menu', | |||
| path: 'menu', | |||
| component: './System/Menu', | |||
| }, | |||
| { | |||
| name: '部门管理', | |||
| path: '/system/dept', | |||
| path: 'dept', | |||
| component: './System/Dept', | |||
| }, | |||
| { | |||
| name: '岗位管理', | |||
| path: '/system/post', | |||
| path: 'post', | |||
| component: './System/Post', | |||
| }, | |||
| { | |||
| name: '字典管理', | |||
| path: '/system/dict', | |||
| path: 'dict', | |||
| component: './System/Dict', | |||
| }, | |||
| { | |||
| name: '字典数据', | |||
| path: '/system/dict-data/index/:id', | |||
| path: 'dict-data/index/:id', | |||
| component: './System/DictData', | |||
| }, | |||
| { | |||
| name: '分配用户', | |||
| path: '/system/role-auth/user/:id', | |||
| path: 'role-auth/user/:id', | |||
| component: './System/Role/authUser', | |||
| }, | |||
| ], | |||
| @@ -181,7 +181,7 @@ export const patchClientRoutes: RuntimeConfig['patchClientRoutes'] = (e) => { | |||
| }; | |||
| export function render(oldRender: () => void) { | |||
| //console.log('render'); | |||
| // console.log('render'); | |||
| const token = getAccessToken(); | |||
| if (!token || token?.length === 0) { | |||
| oldRender(); | |||
| @@ -207,6 +207,7 @@ export const antd: RuntimeAntdConfig = (memo) => { | |||
| colorWarning: themes['warningColor'], | |||
| colorLink: themes['primaryColor'], | |||
| colorText: themes['textColor'], | |||
| controlHeightLG: 46, | |||
| }; | |||
| memo.theme.components ??= {}; | |||
| memo.theme.components.Tabs = {}; | |||
| @@ -1,8 +1,8 @@ | |||
| .container { | |||
| .kf-full-screen-frame { | |||
| width: 100%; | |||
| height: 100%; | |||
| .frame { | |||
| &__iframe { | |||
| width: 100%; | |||
| height: 100%; | |||
| border: none; | |||
| @@ -0,0 +1,18 @@ | |||
| import classNames from 'classnames'; | |||
| import './index.less'; | |||
| type FullScreenFrameProps = { | |||
| url: string; | |||
| className?: string; | |||
| style?: React.CSSProperties; | |||
| }; | |||
| function FullScreenFrame({ url, className, style }: FullScreenFrameProps) { | |||
| return ( | |||
| <div className={classNames('kf-full-screen-frame', className ?? '')} style={style}> | |||
| {url && <iframe src={url} className="kf-full-screen-frame__iframe"></iframe>} | |||
| </div> | |||
| ); | |||
| } | |||
| export default FullScreenFrame; | |||
| @@ -0,0 +1,32 @@ | |||
| .menu-icon-selector { | |||
| // grid 布局,每行显示 8 个图标 | |||
| display: grid; | |||
| grid-auto-rows: 1fr; | |||
| grid-template-columns: repeat(4, 1fr); | |||
| &__item { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| height: 80px; | |||
| cursor: pointer; | |||
| &__icon { | |||
| display: block; | |||
| } | |||
| &__icon--active { | |||
| display: none; | |||
| } | |||
| &:hover &__icon, | |||
| &:active &__icon { | |||
| display: none; | |||
| } | |||
| &:hover &__icon--active, | |||
| &:active &__icon--active { | |||
| display: block; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| import KFIcon from '@/components/KFIcon'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import iconData from '@/iconfont/iconfont.json'; | |||
| import { type ModalProps } from 'antd'; | |||
| import { useEffect, useState } from 'react'; | |||
| import styles from './index.less'; | |||
| interface MenuIconSelectorProps extends Omit<ModalProps, 'onOk'> { | |||
| selectedIcon?: string; | |||
| onOk: (param: string) => void; | |||
| } | |||
| type IconObject = { | |||
| icon_id: string; | |||
| font_class: string; | |||
| }; | |||
| function MenuIconSelector({ open, selectedIcon, onOk, ...rest }: MenuIconSelectorProps) { | |||
| const [icons, setIcons] = useState<IconObject[]>([]); | |||
| useEffect(() => { | |||
| const glyphs = iconData.glyphs as IconObject[]; | |||
| setIcons(glyphs.filter((item) => !item.font_class.endsWith('-active'))); | |||
| }, []); | |||
| return ( | |||
| <KFModal | |||
| {...rest} | |||
| title="选择图标" | |||
| width={680} | |||
| open={open} | |||
| cancelButtonProps={{ style: { display: 'none' } }} | |||
| okButtonProps={{ style: { display: 'none' } }} | |||
| > | |||
| <div className={styles['menu-icon-selector']}> | |||
| {icons.map((icon) => ( | |||
| <div | |||
| key={icon.icon_id} | |||
| className={styles['menu-icon-selector__item']} | |||
| onClick={() => onOk(icon.font_class)} | |||
| > | |||
| <KFIcon | |||
| className={styles['menu-icon-selector__item__icon']} | |||
| type={ | |||
| selectedIcon === icon.font_class | |||
| ? `icon-${icon.font_class}-active` | |||
| : `icon-${icon.font_class}` | |||
| } | |||
| font={24} | |||
| /> | |||
| <KFIcon | |||
| className={styles['menu-icon-selector__item__icon--active']} | |||
| type={`icon-${icon.font_class}-active`} | |||
| font={24} | |||
| /> | |||
| </div> | |||
| ))} | |||
| </div> | |||
| </KFModal> | |||
| ); | |||
| } | |||
| export default MenuIconSelector; | |||
| @@ -0,0 +1,163 @@ | |||
| { | |||
| "id": "4511326", | |||
| "name": "复杂智能软件-导航", | |||
| "font_family": "iconfont", | |||
| "css_prefix_text": "icon-", | |||
| "description": "", | |||
| "glyphs": [ | |||
| { | |||
| "icon_id": "40233218", | |||
| "name": "操作手册-active", | |||
| "font_class": "manual-icon-active", | |||
| "unicode": "e62c", | |||
| "unicode_decimal": 58924 | |||
| }, | |||
| { | |||
| "icon_id": "40233217", | |||
| "name": "操作手册", | |||
| "font_class": "manual-icon", | |||
| "unicode": "e62d", | |||
| "unicode_decimal": 58925 | |||
| }, | |||
| { | |||
| "icon_id": "40171713", | |||
| "name": "监控运维-active", | |||
| "font_class": "monitor-icon-active", | |||
| "unicode": "e627", | |||
| "unicode_decimal": 58919 | |||
| }, | |||
| { | |||
| "icon_id": "40171711", | |||
| "name": "监控运维", | |||
| "font_class": "monitor-icon", | |||
| "unicode": "e629", | |||
| "unicode_decimal": 58921 | |||
| }, | |||
| { | |||
| "icon_id": "40171710", | |||
| "name": "开发环境-active", | |||
| "font_class": "developmentEnvironment-icon-active", | |||
| "unicode": "e62a", | |||
| "unicode_decimal": 58922 | |||
| }, | |||
| { | |||
| "icon_id": "40171699", | |||
| "name": "开发环境", | |||
| "font_class": "developmentEnvironment-icon", | |||
| "unicode": "e62b", | |||
| "unicode_decimal": 58923 | |||
| }, | |||
| { | |||
| "icon_id": "39969575", | |||
| "name": "系统管理", | |||
| "font_class": "system-icon", | |||
| "unicode": "e618", | |||
| "unicode_decimal": 58904 | |||
| }, | |||
| { | |||
| "icon_id": "39969573", | |||
| "name": "流水线-active", | |||
| "font_class": "workflow-icon-active", | |||
| "unicode": "e61a", | |||
| "unicode_decimal": 58906 | |||
| }, | |||
| { | |||
| "icon_id": "39969569", | |||
| "name": "数据准备-active", | |||
| "font_class": "datasetPreparation-icon-active", | |||
| "unicode": "e61c", | |||
| "unicode_decimal": 58908 | |||
| }, | |||
| { | |||
| "icon_id": "39969568", | |||
| "name": "数据准备", | |||
| "font_class": "datasetPreparation-icon", | |||
| "unicode": "e61d", | |||
| "unicode_decimal": 58909 | |||
| }, | |||
| { | |||
| "icon_id": "39969570", | |||
| "name": "模型在线部署", | |||
| "font_class": "modelDseployment-icon", | |||
| "unicode": "e61e", | |||
| "unicode_decimal": 58910 | |||
| }, | |||
| { | |||
| "icon_id": "39969567", | |||
| "name": "流水线", | |||
| "font_class": "workflow-icon", | |||
| "unicode": "e61f", | |||
| "unicode_decimal": 58911 | |||
| }, | |||
| { | |||
| "icon_id": "39969566", | |||
| "name": "AI资产管理-active", | |||
| "font_class": "aiAsset-icon-active", | |||
| "unicode": "e620", | |||
| "unicode_decimal": 58912 | |||
| }, | |||
| { | |||
| "icon_id": "39969563", | |||
| "name": "AI资产管理", | |||
| "font_class": "aiAsset-icon", | |||
| "unicode": "e621", | |||
| "unicode_decimal": 58913 | |||
| }, | |||
| { | |||
| "icon_id": "39969580", | |||
| "name": "工作空间", | |||
| "font_class": "workspace-icon", | |||
| "unicode": "e611", | |||
| "unicode_decimal": 58897 | |||
| }, | |||
| { | |||
| "icon_id": "39969572", | |||
| "name": "模型开发-active", | |||
| "font_class": "model-icon-active", | |||
| "unicode": "e610", | |||
| "unicode_decimal": 58896 | |||
| }, | |||
| { | |||
| "icon_id": "39969579", | |||
| "name": "系统管理-active", | |||
| "font_class": "system-icon-active", | |||
| "unicode": "e612", | |||
| "unicode_decimal": 58898 | |||
| }, | |||
| { | |||
| "icon_id": "39969578", | |||
| "name": "模型在线部署-active", | |||
| "font_class": "modelDseployment-icon-active", | |||
| "unicode": "e613", | |||
| "unicode_decimal": 58899 | |||
| }, | |||
| { | |||
| "icon_id": "39969565", | |||
| "name": "模型开发", | |||
| "font_class": "model-icon", | |||
| "unicode": "e614", | |||
| "unicode_decimal": 58900 | |||
| }, | |||
| { | |||
| "icon_id": "39969577", | |||
| "name": "应用开发", | |||
| "font_class": "appsDeployment-icon", | |||
| "unicode": "e615", | |||
| "unicode_decimal": 58901 | |||
| }, | |||
| { | |||
| "icon_id": "39969576", | |||
| "name": "工作空间-active", | |||
| "font_class": "workspace-icon-active", | |||
| "unicode": "e616", | |||
| "unicode_decimal": 58902 | |||
| }, | |||
| { | |||
| "icon_id": "39969574", | |||
| "name": "应用开发-active", | |||
| "font_class": "appsDeployment-icon-active", | |||
| "unicode": "e617", | |||
| "unicode_decimal": 58903 | |||
| } | |||
| ] | |||
| } | |||
| @@ -120,6 +120,12 @@ | |||
| .ant-select-single { | |||
| height: 46px; | |||
| } | |||
| .ant-input-number { | |||
| .ant-input-number-input { | |||
| height: 44px; | |||
| } | |||
| } | |||
| } | |||
| // Confirm Modal | |||
| @@ -187,3 +193,53 @@ | |||
| .ant-pro-layout .ant-pro-sider-logo > a > h1 { | |||
| margin-inline-start: 12px; | |||
| } | |||
| // PageContainer 里的 ProTable 只滑动内容区域 | |||
| .system-menu.ant-pro-page-container { | |||
| height: 100%; | |||
| overflow: hidden; | |||
| .ant-pro-grid-content { | |||
| height: 100%; | |||
| .ant-pro-grid-content-children { | |||
| height: 100%; | |||
| .ant-pro-layout-watermark-wrapper { | |||
| height: 100%; | |||
| .ant-pro-page-container-children-container { | |||
| height: 100%; | |||
| padding: 0; | |||
| .ant-pro-table { | |||
| display: flex; | |||
| flex-direction: column; | |||
| height: 100%; | |||
| .ant-pro-card.ant-pro-table-search { | |||
| flex: none; | |||
| height: auto; | |||
| } | |||
| .ant-pro-card { | |||
| flex: 1; | |||
| min-height: 0; | |||
| .ant-pro-card-body { | |||
| height: 100%; | |||
| .ant-table-wrapper { | |||
| height: calc(100% - 64px); | |||
| .ant-spin-nested-loading { | |||
| height: 100%; | |||
| .ant-spin-container { | |||
| height: 100%; | |||
| .ant-table-fixed-header { | |||
| height: 100%; | |||
| .ant-table-container { | |||
| height: 100%; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| import FullScreenFrame from '@/components/FullScreenFrame'; | |||
| import { useState } from 'react'; | |||
| function Application() { | |||
| const [iframeUrl] = useState('http://172.20.32.181:30080/'); | |||
| return <FullScreenFrame url={iframeUrl}></FullScreenFrame>; | |||
| } | |||
| export default Application; | |||
| @@ -1,7 +1,7 @@ | |||
| import FullScreenFrame from '@/components/FullScreenFrame'; | |||
| import { getLabelStudioUrl } from '@/services/developmentEnvironment'; | |||
| import { to } from '@/utils/promise'; | |||
| import { useEffect, useState } from 'react'; | |||
| import styles from './index.less'; | |||
| function DatasetAnnotation() { | |||
| const [iframeUrl, setIframeUrl] = useState(''); | |||
| @@ -14,11 +14,7 @@ function DatasetAnnotation() { | |||
| setIframeUrl(res.data); | |||
| } | |||
| }; | |||
| return ( | |||
| <div className={styles.container}> | |||
| {iframeUrl && <iframe src={iframeUrl} className={styles.frame}></iframe>} | |||
| </div> | |||
| ); | |||
| return <FullScreenFrame url={iframeUrl} />; | |||
| } | |||
| export default DatasetAnnotation; | |||
| @@ -93,8 +93,7 @@ function ExperimentComparison() { | |||
| type: 'checkbox', | |||
| fixed: 'left', | |||
| selectedRowKeys, | |||
| onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => { | |||
| // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); | |||
| onChange: (selectedRowKeys: React.Key[]) => { | |||
| setSelectedRowKeys(selectedRowKeys); | |||
| }, | |||
| }; | |||
| @@ -159,6 +158,8 @@ function ExperimentComparison() { | |||
| align: 'center', | |||
| render: tableCellRender(true), | |||
| ellipsis: { showTitle: false }, | |||
| sorter: (a, b) => a.params[name] - b.params[name], | |||
| showSorterTooltip: false, | |||
| })), | |||
| }, | |||
| { | |||
| @@ -176,6 +177,8 @@ function ExperimentComparison() { | |||
| align: 'center', | |||
| render: tableCellRender(true), | |||
| ellipsis: { showTitle: false }, | |||
| sorter: (a, b) => a.metrics[name] - b.metrics[name], | |||
| showSorterTooltip: false, | |||
| })), | |||
| }, | |||
| ]; | |||
| @@ -319,8 +319,8 @@ const JobTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.Monitor.Job> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -333,6 +333,9 @@ const JobTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -365,7 +368,7 @@ const JobTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -376,7 +379,7 @@ const JobTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -217,8 +217,8 @@ const JobLogTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.Monitor.JobLog> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -231,6 +231,9 @@ const JobLogTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -263,7 +266,7 @@ const JobLogTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -274,7 +277,7 @@ const JobLogTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -258,8 +258,8 @@ const ConfigTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.Config> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -272,6 +272,9 @@ const ConfigTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -305,7 +308,7 @@ const ConfigTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -316,7 +319,7 @@ const ConfigTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <DownloadOutlined /> | |||
| <DownloadOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -234,8 +234,8 @@ const DeptTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.Dept> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -248,6 +248,9 @@ const DeptTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -287,7 +290,7 @@ const DeptTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -298,7 +301,7 @@ const DeptTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -259,8 +259,8 @@ const DictTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.DictType> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -273,6 +273,9 @@ const DictTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -305,7 +308,7 @@ const DictTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -316,7 +319,7 @@ const DictTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -303,8 +303,8 @@ const DictDataTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.DictData> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -317,6 +317,9 @@ const DictDataTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -353,7 +356,7 @@ const DictDataTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -364,7 +367,7 @@ const DictDataTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -180,8 +180,8 @@ const LogininforTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.Monitor.Logininfor> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -194,6 +194,9 @@ const LogininforTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| key="remove" | |||
| @@ -215,7 +218,7 @@ const LogininforTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -239,7 +242,7 @@ const LogininforTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.cleanAll" defaultMessage="清空" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -262,7 +265,7 @@ const LogininforTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <UnlockOutlined /> | |||
| <UnlockOutlined />{' '} | |||
| <FormattedMessage id="monitor.logininfor.unlock" defaultMessage="解锁" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -273,7 +276,7 @@ const LogininforTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -1,7 +1,7 @@ | |||
| import { DictValueEnumObj } from '@/components/DictTag'; | |||
| import IconSelector from '@/components/IconSelector'; | |||
| import KFModal from '@/components/KFModal'; | |||
| import { createIcon } from '@/utils/IconUtil'; | |||
| import MenuIconSelector from '@/components/MenuIconSelector'; | |||
| import { openAntdModal } from '@/utils/modal'; | |||
| import { | |||
| ProForm, | |||
| ProFormDigit, | |||
| @@ -27,31 +27,39 @@ export type MenuFormProps = { | |||
| menuTree: DataNode[]; | |||
| }; | |||
| const formLayout = { | |||
| labelCol: { span: 8 }, | |||
| wrapperCol: { span: 16 }, | |||
| }; | |||
| const formItemLayout = { | |||
| labelCol: { span: 4 }, | |||
| wrapperCol: { span: 20 }, | |||
| }; | |||
| const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| const [form] = Form.useForm(); | |||
| const [menuTypeId, setMenuTypeId] = useState<any>('M'); | |||
| const [menuTypeId, setMenuTypeId] = useState<any>(); | |||
| const [menuIconName, setMenuIconName] = useState<any>(); | |||
| const [iconSelectorOpen, setIconSelectorOpen] = useState<boolean>(false); | |||
| const { menuTree, visibleOptions, statusOptions } = props; | |||
| useEffect(() => { | |||
| form.resetFields(); | |||
| setMenuIconName(props.values.icon); | |||
| setMenuTypeId(props.values.menuType ?? 'M'); | |||
| form.setFieldsValue({ | |||
| menuId: props.values.menuId, | |||
| menuName: props.values.menuName, | |||
| parentId: props.values.parentId, | |||
| orderNum: props.values.orderNum, | |||
| parentId: props.values.parentId ?? 0, | |||
| orderNum: props.values.orderNum ?? 1, | |||
| path: props.values.path, | |||
| component: props.values.component, | |||
| query: props.values.query, | |||
| isFrame: props.values.isFrame, | |||
| isCache: props.values.isCache, | |||
| menuType: props.values.menuType, | |||
| visible: props.values.visible, | |||
| status: props.values.status, | |||
| isFrame: props.values.isFrame ?? '1', | |||
| isCache: props.values.isCache ?? '1', | |||
| menuType: props.values.menuType ?? 'M', | |||
| visible: props.values.visible ?? Object.keys(visibleOptions)[0], | |||
| status: props.values.status ?? Object.keys(statusOptions)[0], | |||
| perms: props.values.perms, | |||
| icon: props.values.icon, | |||
| createBy: props.values.createBy, | |||
| @@ -73,9 +81,20 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| props.onSubmit(values as MenuFormData); | |||
| }; | |||
| const selectIcon = () => { | |||
| const { close } = openAntdModal(MenuIconSelector, { | |||
| selectedIcon: menuIconName, | |||
| onOk: (icon) => { | |||
| setMenuIconName(icon); | |||
| form.setFieldsValue({ icon }); | |||
| close(); | |||
| }, | |||
| }); | |||
| }; | |||
| return ( | |||
| <KFModal | |||
| width={640} | |||
| width={680} | |||
| title={intl.formatMessage({ | |||
| id: 'system.menu.title', | |||
| defaultMessage: '编辑菜单权限', | |||
| @@ -92,6 +111,8 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| submitter={false} | |||
| layout="horizontal" | |||
| onFinish={handleFinish} | |||
| {...formLayout} | |||
| size="large" | |||
| > | |||
| <ProFormDigit | |||
| name="menuId" | |||
| @@ -110,6 +131,7 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| ]} | |||
| /> | |||
| <ProFormTreeSelect | |||
| {...formItemLayout} | |||
| name="parentId" | |||
| label={intl.formatMessage({ | |||
| id: 'system.menu.parent_id', | |||
| @@ -128,11 +150,9 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| ), | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: 0, | |||
| }} | |||
| /> | |||
| <ProFormRadio.Group | |||
| {...formItemLayout} | |||
| name="menuType" | |||
| valueEnum={{ | |||
| M: '目录', | |||
| @@ -151,13 +171,13 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: 'M', | |||
| onChange: (e) => { | |||
| setMenuTypeId(e.target.value); | |||
| }, | |||
| }} | |||
| /> | |||
| <ProFormSelect | |||
| {...formItemLayout} | |||
| name="icon" | |||
| label={intl.formatMessage({ | |||
| id: 'system.menu.icon', | |||
| @@ -165,10 +185,10 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| })} | |||
| valueEnum={{}} | |||
| hidden={menuTypeId === 'F'} | |||
| addonBefore={createIcon(menuIconName)} | |||
| // addonBefore={createIcon(menuIconName)} | |||
| fieldProps={{ | |||
| onClick: () => { | |||
| setIconSelectorOpen(true); | |||
| selectIcon(); | |||
| }, | |||
| }} | |||
| placeholder="请输入菜单图标" | |||
| @@ -209,9 +229,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| message: <FormattedMessage id="请输入显示顺序!" defaultMessage="请输入显示顺序!" />, | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: 1, | |||
| }} | |||
| /> | |||
| <ProFormRadio.Group | |||
| name="isFrame" | |||
| @@ -219,7 +236,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| 0: '是', | |||
| 1: '否', | |||
| }} | |||
| initialValue="1" | |||
| label={intl.formatMessage({ | |||
| id: 'system.menu.is_frame', | |||
| defaultMessage: '是否为外链', | |||
| @@ -235,9 +251,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| ), | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: '1', | |||
| }} | |||
| /> | |||
| <ProFormText | |||
| name="path" | |||
| @@ -323,9 +336,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| message: <FormattedMessage id="请输入是否缓存!" defaultMessage="请输入是否缓存!" />, | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: 0, | |||
| }} | |||
| /> | |||
| <ProFormRadio.Group | |||
| name="visible" | |||
| @@ -343,9 +353,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| message: <FormattedMessage id="请输入显示状态!" defaultMessage="请输入显示状态!" />, | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: '0', | |||
| }} | |||
| /> | |||
| <ProFormRadio.Group | |||
| valueEnum={statusOptions} | |||
| @@ -363,27 +370,8 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||
| message: <FormattedMessage id="请输入菜单状态!" defaultMessage="请输入菜单状态!" />, | |||
| }, | |||
| ]} | |||
| fieldProps={{ | |||
| defaultValue: '0', | |||
| }} | |||
| /> | |||
| </ProForm> | |||
| <KFModal | |||
| width={800} | |||
| open={iconSelectorOpen} | |||
| onCancel={() => { | |||
| setIconSelectorOpen(false); | |||
| }} | |||
| footer={null} | |||
| > | |||
| <IconSelector | |||
| onSelect={(name: string) => { | |||
| form.setFieldsValue({ icon: name }); | |||
| setMenuIconName(name); | |||
| setIconSelectorOpen(false); | |||
| }} | |||
| /> | |||
| </KFModal> | |||
| </KFModal> | |||
| ); | |||
| }; | |||
| @@ -221,8 +221,8 @@ const MenuTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.Menu> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -234,6 +234,9 @@ const MenuTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -266,7 +269,7 @@ const MenuTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -277,7 +280,7 @@ const MenuTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -259,8 +259,8 @@ const NoticeTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.Notice> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -273,6 +273,9 @@ const NoticeTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -305,7 +308,7 @@ const NoticeTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -316,7 +319,7 @@ const NoticeTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -227,8 +227,8 @@ const OperlogTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.Monitor.Operlog> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -241,6 +241,9 @@ const OperlogTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -273,7 +276,7 @@ const OperlogTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -284,7 +287,7 @@ const OperlogTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -225,8 +225,8 @@ const PostTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.Post> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -239,6 +239,9 @@ const PostTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -271,7 +274,7 @@ const PostTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -282,7 +285,7 @@ const PostTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -163,8 +163,8 @@ const AuthUserTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.User> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -176,6 +176,9 @@ const AuthUserTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -208,7 +211,7 @@ const AuthUserTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="system.role.auth.cancelAll" defaultMessage="批量取消授权" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -218,8 +221,7 @@ const AuthUserTableList: React.FC = () => { | |||
| history.back(); | |||
| }} | |||
| > | |||
| <RollbackOutlined /> | |||
| <FormattedMessage id="pages.goback" defaultMessage="返回" /> | |||
| <RollbackOutlined /> <FormattedMessage id="pages.goback" defaultMessage="返回" /> | |||
| </Button>, | |||
| ]} | |||
| request={(params) => | |||
| @@ -360,9 +360,9 @@ const RoleTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| {contextHolder} | |||
| <div style={{ width: '100%', float: 'right' }}> | |||
| <div style={{ width: '100%', height: '100%' }}> | |||
| <ProTable<API.System.Role> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -375,6 +375,9 @@ const RoleTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -416,7 +419,7 @@ const RoleTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -427,7 +430,7 @@ const RoleTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -365,10 +365,10 @@ const UserTableList: React.FC = () => { | |||
| ]; | |||
| return ( | |||
| <PageContainer header={{ breadcrumb: {} }}> | |||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||
| {contextHolder} | |||
| <Row gutter={[16, 24]}> | |||
| <Col lg={6} md={24}> | |||
| <Row gutter={[16, 24]} style={{ height: '100%' }}> | |||
| <Col lg={6} md={24} style={{ height: '100%' }}> | |||
| <Card> | |||
| <DeptTree | |||
| onSelect={async (value: any) => { | |||
| @@ -380,7 +380,7 @@ const UserTableList: React.FC = () => { | |||
| /> | |||
| </Card> | |||
| </Col> | |||
| <Col lg={18} md={24}> | |||
| <Col lg={18} md={24} style={{ height: '100%' }}> | |||
| <ProTable<API.System.User> | |||
| headerTitle={intl.formatMessage({ | |||
| id: 'pages.searchTable.title', | |||
| @@ -393,6 +393,9 @@ const UserTableList: React.FC = () => { | |||
| search={{ | |||
| labelWidth: 120, | |||
| }} | |||
| scroll={{ y: 'calc(100% - 55px)' }} | |||
| tableAlertRender={false} | |||
| tableAlertOptionRender={false} | |||
| toolBarRender={() => [ | |||
| <Button | |||
| type="primary" | |||
| @@ -452,7 +455,7 @@ const UserTableList: React.FC = () => { | |||
| }); | |||
| }} | |||
| > | |||
| <DeleteOutlined /> | |||
| <DeleteOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | |||
| </Button>, | |||
| <Button | |||
| @@ -463,7 +466,7 @@ const UserTableList: React.FC = () => { | |||
| handleExport(); | |||
| }} | |||
| > | |||
| <PlusOutlined /> | |||
| <PlusOutlined />{' '} | |||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | |||
| </Button>, | |||
| ]} | |||
| @@ -18,7 +18,7 @@ const CacheInfo: React.FC = () => { | |||
| }); | |||
| return ( | |||
| <div style={{}}> | |||
| <div> | |||
| <iframe | |||
| style={{ width: '100%', border: '0px', height: '100%' }} | |||
| src={`/api/swagger-ui/index.html`} | |||
| @@ -49,6 +49,7 @@ | |||
| position: fixed; | |||
| right: 30px; | |||
| bottom: 20px; | |||
| z-index: 99; | |||
| width: 64px; | |||
| height: 64px; | |||
| background-color: white; | |||
| @@ -71,7 +71,7 @@ function Workspace() { | |||
| <AssetsManagement></AssetsManagement> | |||
| </div> | |||
| </div> | |||
| <Draggable onStart={handleStart} onStop={handleStop} onDrag={handleDrag}> | |||
| <Draggable onStart={handleStart} onStop={handleStop} onDrag={handleDrag} bounds="body"> | |||
| <img | |||
| className={styles['workspace__robot-img']} | |||
| src={require('@/assets/img/robot.png')} | |||
| @@ -7,10 +7,9 @@ export function getJupyterUrl() { | |||
| } | |||
| // 查询 labelStudio url | |||
| export function getLabelStudioUrl(params: any) { | |||
| export function getLabelStudioUrl() { | |||
| return request(`/api/mmp/labelStudio/getURL`, { | |||
| method: 'GET', | |||
| params, | |||
| }); | |||
| } | |||
| @@ -2,7 +2,7 @@ import { MenuDataItem } from '@ant-design/pro-components'; | |||
| import { request } from '@umijs/max'; | |||
| import React, { lazy } from 'react'; | |||
| let remoteMenu: any = []; | |||
| let remoteMenu: any = null; | |||
| export function getRemoteMenu() { | |||
| return remoteMenu; | |||
| @@ -12,30 +12,35 @@ export function setRemoteMenu(data: any) { | |||
| remoteMenu = data; | |||
| } | |||
| // 根据后台配置的菜单路径获取本地路由 | |||
| const getLocalRoute = (route: any, menuItem: any) => { | |||
| for (const routeChild of route.routes) { | |||
| if (routeChild.path === menuItem.path) { | |||
| return routeChild; | |||
| } | |||
| } | |||
| return null; | |||
| }; | |||
| function patchRouteItems(route: any, menu: any, parentPath: string) { | |||
| for (const menuItem of menu) { | |||
| if (menuItem.component === 'Layout' || menuItem.component === 'ParentView') { | |||
| if (menuItem.routes) { | |||
| let hasItem = false; | |||
| let newItem = null; | |||
| for (const routeChild of route.routes) { | |||
| if (routeChild.path === menuItem.path) { | |||
| hasItem = true; | |||
| newItem = routeChild; | |||
| break; | |||
| } | |||
| } | |||
| if (!hasItem) { | |||
| let newItem = getLocalRoute(route, menuItem); | |||
| if (!newItem) { | |||
| newItem = { | |||
| path: menuItem.path, | |||
| routes: [], | |||
| children: [], | |||
| }; | |||
| route.children = route.routes; | |||
| route.routes.push(newItem); | |||
| } | |||
| patchRouteItems(newItem, menuItem.routes, parentPath + menuItem.path + '/'); | |||
| } | |||
| } else { | |||
| if (getLocalRoute(route, menuItem)) { | |||
| return; | |||
| } | |||
| const names: string[] = menuItem.component.split('/'); | |||
| let path = ''; | |||
| names.forEach((name) => { | |||
| @@ -53,17 +58,13 @@ function patchRouteItems(route: any, menu: any, parentPath: string) { | |||
| } | |||
| if (route.routes === undefined) { | |||
| route.routes = []; | |||
| route.children = route.routes; | |||
| } | |||
| if (route.children === undefined) { | |||
| route.children = []; | |||
| } | |||
| const newRoute = { | |||
| element: React.createElement(lazy(() => import('@/pages/' + path))), | |||
| path: parentPath + menuItem.path, | |||
| }; | |||
| // console.log(newRoute); | |||
| route.children.push(newRoute); | |||
| route.routes.push(newRoute); | |||
| } | |||
| } | |||