| @@ -20,16 +20,16 @@ export default { | |||||
| // localhost:8000/api/** -> https://preview.pro.ant.design/api/** | // localhost:8000/api/** -> https://preview.pro.ant.design/api/** | ||||
| '/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', | // target: 'http://172.20.32.150:8082', | ||||
| // 配置了这个可以从 http 代理到 https | // 配置了这个可以从 http 代理到 https | ||||
| // 依赖 origin 的功能可能需要这个,比如 cookie | // 依赖 origin 的功能可能需要这个,比如 cookie | ||||
| changeOrigin: true, | changeOrigin: true, | ||||
| pathRewrite: { '^/api': '' }, | |||||
| // pathRewrite: { '^/api': '' }, | |||||
| }, | }, | ||||
| '/profile/avatar/': { | '/profile/avatar/': { | ||||
| target: 'http://172.20.32.181:31205', | |||||
| target: 'http://172.20.32.181:31213', | |||||
| changeOrigin: true, | changeOrigin: true, | ||||
| }, | }, | ||||
| }, | }, | ||||
| @@ -14,10 +14,9 @@ export default [ | |||||
| { | { | ||||
| path: '/', | path: '/', | ||||
| redirect: '/workspace', | redirect: '/workspace', | ||||
| breadcrumb: '工作空间', | |||||
| }, | }, | ||||
| { | { | ||||
| name: 'workspace', | |||||
| name: '工作空间', | |||||
| path: '/workspace', | path: '/workspace', | ||||
| routes: [ | routes: [ | ||||
| { | { | ||||
| @@ -41,6 +40,7 @@ export default [ | |||||
| }, | }, | ||||
| { | { | ||||
| path: '/account', | path: '/account', | ||||
| name: '用户中心', | |||||
| routes: [ | routes: [ | ||||
| { | { | ||||
| name: '用户中心', | name: '用户中心', | ||||
| @@ -70,7 +70,7 @@ export default [ | |||||
| ], | ], | ||||
| }, | }, | ||||
| { | { | ||||
| name: 'developmentEnvironment', | |||||
| name: '开发环境', | |||||
| path: '/developmentEnvironment', | path: '/developmentEnvironment', | ||||
| routes: [ | routes: [ | ||||
| { | { | ||||
| @@ -79,12 +79,12 @@ export default [ | |||||
| component: './DevelopmentEnvironment/Editor', | component: './DevelopmentEnvironment/Editor', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '创建编辑器', | |||||
| name: '创建开发环境', | |||||
| path: 'create', | path: 'create', | ||||
| component: './DevelopmentEnvironment/Create', | component: './DevelopmentEnvironment/Create', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '编辑器', | |||||
| name: '开发环境详情', | |||||
| path: 'editor', | path: 'editor', | ||||
| component: './DevelopmentEnvironment/Editor', | component: './DevelopmentEnvironment/Editor', | ||||
| }, | }, | ||||
| @@ -229,7 +229,7 @@ export default [ | |||||
| name: '应用开发', | name: '应用开发', | ||||
| path: '', | path: '', | ||||
| key: 'appsDeployment', | key: 'appsDeployment', | ||||
| component: './missingPage.jsx', | |||||
| component: './Application', | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| @@ -306,47 +306,47 @@ export default [ | |||||
| }, | }, | ||||
| { | { | ||||
| name: '用户管理', | name: '用户管理', | ||||
| path: '/system/user', | |||||
| path: 'user', | |||||
| component: './System/User', | component: './System/User', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '角色管理', | name: '角色管理', | ||||
| path: '/system/role', | |||||
| path: 'role', | |||||
| component: './System/Role', | component: './System/Role', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '定时任务', | name: '定时任务', | ||||
| path: '/system/job', | |||||
| path: 'job', | |||||
| component: './Monitor/Job', | component: './Monitor/Job', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '菜单管理', | name: '菜单管理', | ||||
| path: '/system/menu', | |||||
| path: 'menu', | |||||
| component: './System/Menu', | component: './System/Menu', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '部门管理', | name: '部门管理', | ||||
| path: '/system/dept', | |||||
| path: 'dept', | |||||
| component: './System/Dept', | component: './System/Dept', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '岗位管理', | name: '岗位管理', | ||||
| path: '/system/post', | |||||
| path: 'post', | |||||
| component: './System/Post', | component: './System/Post', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '字典管理', | name: '字典管理', | ||||
| path: '/system/dict', | |||||
| path: 'dict', | |||||
| component: './System/Dict', | component: './System/Dict', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '字典数据', | name: '字典数据', | ||||
| path: '/system/dict-data/index/:id', | |||||
| path: 'dict-data/index/:id', | |||||
| component: './System/DictData', | component: './System/DictData', | ||||
| }, | }, | ||||
| { | { | ||||
| name: '分配用户', | name: '分配用户', | ||||
| path: '/system/role-auth/user/:id', | |||||
| path: 'role-auth/user/:id', | |||||
| component: './System/Role/authUser', | component: './System/Role/authUser', | ||||
| }, | }, | ||||
| ], | ], | ||||
| @@ -181,7 +181,7 @@ export const patchClientRoutes: RuntimeConfig['patchClientRoutes'] = (e) => { | |||||
| }; | }; | ||||
| export function render(oldRender: () => void) { | export function render(oldRender: () => void) { | ||||
| //console.log('render'); | |||||
| // console.log('render'); | |||||
| const token = getAccessToken(); | const token = getAccessToken(); | ||||
| if (!token || token?.length === 0) { | if (!token || token?.length === 0) { | ||||
| oldRender(); | oldRender(); | ||||
| @@ -207,6 +207,7 @@ export const antd: RuntimeAntdConfig = (memo) => { | |||||
| colorWarning: themes['warningColor'], | colorWarning: themes['warningColor'], | ||||
| colorLink: themes['primaryColor'], | colorLink: themes['primaryColor'], | ||||
| colorText: themes['textColor'], | colorText: themes['textColor'], | ||||
| controlHeightLG: 46, | |||||
| }; | }; | ||||
| memo.theme.components ??= {}; | memo.theme.components ??= {}; | ||||
| memo.theme.components.Tabs = {}; | memo.theme.components.Tabs = {}; | ||||
| @@ -1,8 +1,8 @@ | |||||
| .container { | |||||
| .kf-full-screen-frame { | |||||
| width: 100%; | width: 100%; | ||||
| height: 100%; | height: 100%; | ||||
| .frame { | |||||
| &__iframe { | |||||
| width: 100%; | width: 100%; | ||||
| height: 100%; | height: 100%; | ||||
| border: none; | 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 { | .ant-select-single { | ||||
| height: 46px; | height: 46px; | ||||
| } | } | ||||
| .ant-input-number { | |||||
| .ant-input-number-input { | |||||
| height: 44px; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| // Confirm Modal | // Confirm Modal | ||||
| @@ -187,3 +193,53 @@ | |||||
| .ant-pro-layout .ant-pro-sider-logo > a > h1 { | .ant-pro-layout .ant-pro-sider-logo > a > h1 { | ||||
| margin-inline-start: 12px; | 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 { getLabelStudioUrl } from '@/services/developmentEnvironment'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import styles from './index.less'; | |||||
| function DatasetAnnotation() { | function DatasetAnnotation() { | ||||
| const [iframeUrl, setIframeUrl] = useState(''); | const [iframeUrl, setIframeUrl] = useState(''); | ||||
| @@ -14,11 +14,7 @@ function DatasetAnnotation() { | |||||
| setIframeUrl(res.data); | setIframeUrl(res.data); | ||||
| } | } | ||||
| }; | }; | ||||
| return ( | |||||
| <div className={styles.container}> | |||||
| {iframeUrl && <iframe src={iframeUrl} className={styles.frame}></iframe>} | |||||
| </div> | |||||
| ); | |||||
| return <FullScreenFrame url={iframeUrl} />; | |||||
| } | } | ||||
| export default DatasetAnnotation; | export default DatasetAnnotation; | ||||
| @@ -93,8 +93,7 @@ function ExperimentComparison() { | |||||
| type: 'checkbox', | type: 'checkbox', | ||||
| fixed: 'left', | fixed: 'left', | ||||
| selectedRowKeys, | selectedRowKeys, | ||||
| onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => { | |||||
| // console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); | |||||
| onChange: (selectedRowKeys: React.Key[]) => { | |||||
| setSelectedRowKeys(selectedRowKeys); | setSelectedRowKeys(selectedRowKeys); | ||||
| }, | }, | ||||
| }; | }; | ||||
| @@ -159,6 +158,8 @@ function ExperimentComparison() { | |||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | ellipsis: { showTitle: false }, | ||||
| sorter: (a, b) => a.params[name] - b.params[name], | |||||
| showSorterTooltip: false, | |||||
| })), | })), | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -176,6 +177,8 @@ function ExperimentComparison() { | |||||
| align: 'center', | align: 'center', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| ellipsis: { showTitle: false }, | ellipsis: { showTitle: false }, | ||||
| sorter: (a, b) => a.metrics[name] - b.metrics[name], | |||||
| showSorterTooltip: false, | |||||
| })), | })), | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| @@ -319,8 +319,8 @@ const JobTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.Monitor.Job> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -333,6 +333,9 @@ const JobTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -365,7 +368,7 @@ const JobTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -376,7 +379,7 @@ const JobTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -217,8 +217,8 @@ const JobLogTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.Monitor.JobLog> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -231,6 +231,9 @@ const JobLogTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -263,7 +266,7 @@ const JobLogTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -274,7 +277,7 @@ const JobLogTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -258,8 +258,8 @@ const ConfigTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.Config> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -272,6 +272,9 @@ const ConfigTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -305,7 +308,7 @@ const ConfigTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -316,7 +319,7 @@ const ConfigTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <DownloadOutlined /> | |||||
| <DownloadOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -234,8 +234,8 @@ const DeptTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.Dept> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -248,6 +248,9 @@ const DeptTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -287,7 +290,7 @@ const DeptTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -298,7 +301,7 @@ const DeptTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -259,8 +259,8 @@ const DictTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.DictType> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -273,6 +273,9 @@ const DictTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -305,7 +308,7 @@ const DictTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -316,7 +319,7 @@ const DictTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -303,8 +303,8 @@ const DictDataTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.DictData> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -317,6 +317,9 @@ const DictDataTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -353,7 +356,7 @@ const DictDataTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -364,7 +367,7 @@ const DictDataTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -180,8 +180,8 @@ const LogininforTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.Monitor.Logininfor> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -194,6 +194,9 @@ const LogininforTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| key="remove" | key="remove" | ||||
| @@ -215,7 +218,7 @@ const LogininforTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -239,7 +242,7 @@ const LogininforTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.cleanAll" defaultMessage="清空" /> | <FormattedMessage id="pages.searchTable.cleanAll" defaultMessage="清空" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -262,7 +265,7 @@ const LogininforTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <UnlockOutlined /> | |||||
| <UnlockOutlined />{' '} | |||||
| <FormattedMessage id="monitor.logininfor.unlock" defaultMessage="解锁" /> | <FormattedMessage id="monitor.logininfor.unlock" defaultMessage="解锁" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -273,7 +276,7 @@ const LogininforTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -1,7 +1,7 @@ | |||||
| import { DictValueEnumObj } from '@/components/DictTag'; | import { DictValueEnumObj } from '@/components/DictTag'; | ||||
| import IconSelector from '@/components/IconSelector'; | |||||
| import KFModal from '@/components/KFModal'; | import KFModal from '@/components/KFModal'; | ||||
| import { createIcon } from '@/utils/IconUtil'; | |||||
| import MenuIconSelector from '@/components/MenuIconSelector'; | |||||
| import { openAntdModal } from '@/utils/modal'; | |||||
| import { | import { | ||||
| ProForm, | ProForm, | ||||
| ProFormDigit, | ProFormDigit, | ||||
| @@ -27,31 +27,39 @@ export type MenuFormProps = { | |||||
| menuTree: DataNode[]; | 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 MenuForm: React.FC<MenuFormProps> = (props) => { | ||||
| const [form] = Form.useForm(); | const [form] = Form.useForm(); | ||||
| const [menuTypeId, setMenuTypeId] = useState<any>('M'); | |||||
| const [menuTypeId, setMenuTypeId] = useState<any>(); | |||||
| const [menuIconName, setMenuIconName] = useState<any>(); | const [menuIconName, setMenuIconName] = useState<any>(); | ||||
| const [iconSelectorOpen, setIconSelectorOpen] = useState<boolean>(false); | |||||
| const { menuTree, visibleOptions, statusOptions } = props; | const { menuTree, visibleOptions, statusOptions } = props; | ||||
| useEffect(() => { | useEffect(() => { | ||||
| form.resetFields(); | form.resetFields(); | ||||
| setMenuIconName(props.values.icon); | setMenuIconName(props.values.icon); | ||||
| setMenuTypeId(props.values.menuType ?? 'M'); | |||||
| form.setFieldsValue({ | form.setFieldsValue({ | ||||
| menuId: props.values.menuId, | menuId: props.values.menuId, | ||||
| menuName: props.values.menuName, | 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, | path: props.values.path, | ||||
| component: props.values.component, | component: props.values.component, | ||||
| query: props.values.query, | 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, | perms: props.values.perms, | ||||
| icon: props.values.icon, | icon: props.values.icon, | ||||
| createBy: props.values.createBy, | createBy: props.values.createBy, | ||||
| @@ -73,9 +81,20 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| props.onSubmit(values as MenuFormData); | props.onSubmit(values as MenuFormData); | ||||
| }; | }; | ||||
| const selectIcon = () => { | |||||
| const { close } = openAntdModal(MenuIconSelector, { | |||||
| selectedIcon: menuIconName, | |||||
| onOk: (icon) => { | |||||
| setMenuIconName(icon); | |||||
| form.setFieldsValue({ icon }); | |||||
| close(); | |||||
| }, | |||||
| }); | |||||
| }; | |||||
| return ( | return ( | ||||
| <KFModal | <KFModal | ||||
| width={640} | |||||
| width={680} | |||||
| title={intl.formatMessage({ | title={intl.formatMessage({ | ||||
| id: 'system.menu.title', | id: 'system.menu.title', | ||||
| defaultMessage: '编辑菜单权限', | defaultMessage: '编辑菜单权限', | ||||
| @@ -92,6 +111,8 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| submitter={false} | submitter={false} | ||||
| layout="horizontal" | layout="horizontal" | ||||
| onFinish={handleFinish} | onFinish={handleFinish} | ||||
| {...formLayout} | |||||
| size="large" | |||||
| > | > | ||||
| <ProFormDigit | <ProFormDigit | ||||
| name="menuId" | name="menuId" | ||||
| @@ -110,6 +131,7 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| ]} | ]} | ||||
| /> | /> | ||||
| <ProFormTreeSelect | <ProFormTreeSelect | ||||
| {...formItemLayout} | |||||
| name="parentId" | name="parentId" | ||||
| label={intl.formatMessage({ | label={intl.formatMessage({ | ||||
| id: 'system.menu.parent_id', | id: 'system.menu.parent_id', | ||||
| @@ -128,11 +150,9 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| ), | ), | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | |||||
| defaultValue: 0, | |||||
| }} | |||||
| /> | /> | ||||
| <ProFormRadio.Group | <ProFormRadio.Group | ||||
| {...formItemLayout} | |||||
| name="menuType" | name="menuType" | ||||
| valueEnum={{ | valueEnum={{ | ||||
| M: '目录', | M: '目录', | ||||
| @@ -151,13 +171,13 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | fieldProps={{ | ||||
| defaultValue: 'M', | |||||
| onChange: (e) => { | onChange: (e) => { | ||||
| setMenuTypeId(e.target.value); | setMenuTypeId(e.target.value); | ||||
| }, | }, | ||||
| }} | }} | ||||
| /> | /> | ||||
| <ProFormSelect | <ProFormSelect | ||||
| {...formItemLayout} | |||||
| name="icon" | name="icon" | ||||
| label={intl.formatMessage({ | label={intl.formatMessage({ | ||||
| id: 'system.menu.icon', | id: 'system.menu.icon', | ||||
| @@ -165,10 +185,10 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| })} | })} | ||||
| valueEnum={{}} | valueEnum={{}} | ||||
| hidden={menuTypeId === 'F'} | hidden={menuTypeId === 'F'} | ||||
| addonBefore={createIcon(menuIconName)} | |||||
| // addonBefore={createIcon(menuIconName)} | |||||
| fieldProps={{ | fieldProps={{ | ||||
| onClick: () => { | onClick: () => { | ||||
| setIconSelectorOpen(true); | |||||
| selectIcon(); | |||||
| }, | }, | ||||
| }} | }} | ||||
| placeholder="请输入菜单图标" | placeholder="请输入菜单图标" | ||||
| @@ -209,9 +229,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| message: <FormattedMessage id="请输入显示顺序!" defaultMessage="请输入显示顺序!" />, | message: <FormattedMessage id="请输入显示顺序!" defaultMessage="请输入显示顺序!" />, | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | |||||
| defaultValue: 1, | |||||
| }} | |||||
| /> | /> | ||||
| <ProFormRadio.Group | <ProFormRadio.Group | ||||
| name="isFrame" | name="isFrame" | ||||
| @@ -219,7 +236,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| 0: '是', | 0: '是', | ||||
| 1: '否', | 1: '否', | ||||
| }} | }} | ||||
| initialValue="1" | |||||
| label={intl.formatMessage({ | label={intl.formatMessage({ | ||||
| id: 'system.menu.is_frame', | id: 'system.menu.is_frame', | ||||
| defaultMessage: '是否为外链', | defaultMessage: '是否为外链', | ||||
| @@ -235,9 +251,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| ), | ), | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | |||||
| defaultValue: '1', | |||||
| }} | |||||
| /> | /> | ||||
| <ProFormText | <ProFormText | ||||
| name="path" | name="path" | ||||
| @@ -323,9 +336,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| message: <FormattedMessage id="请输入是否缓存!" defaultMessage="请输入是否缓存!" />, | message: <FormattedMessage id="请输入是否缓存!" defaultMessage="请输入是否缓存!" />, | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | |||||
| defaultValue: 0, | |||||
| }} | |||||
| /> | /> | ||||
| <ProFormRadio.Group | <ProFormRadio.Group | ||||
| name="visible" | name="visible" | ||||
| @@ -343,9 +353,6 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| message: <FormattedMessage id="请输入显示状态!" defaultMessage="请输入显示状态!" />, | message: <FormattedMessage id="请输入显示状态!" defaultMessage="请输入显示状态!" />, | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | |||||
| defaultValue: '0', | |||||
| }} | |||||
| /> | /> | ||||
| <ProFormRadio.Group | <ProFormRadio.Group | ||||
| valueEnum={statusOptions} | valueEnum={statusOptions} | ||||
| @@ -363,27 +370,8 @@ const MenuForm: React.FC<MenuFormProps> = (props) => { | |||||
| message: <FormattedMessage id="请输入菜单状态!" defaultMessage="请输入菜单状态!" />, | message: <FormattedMessage id="请输入菜单状态!" defaultMessage="请输入菜单状态!" />, | ||||
| }, | }, | ||||
| ]} | ]} | ||||
| fieldProps={{ | |||||
| defaultValue: '0', | |||||
| }} | |||||
| /> | /> | ||||
| </ProForm> | </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> | </KFModal> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -221,8 +221,8 @@ const MenuTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.Menu> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -234,6 +234,9 @@ const MenuTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -266,7 +269,7 @@ const MenuTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -277,7 +280,7 @@ const MenuTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -259,8 +259,8 @@ const NoticeTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.Notice> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -273,6 +273,9 @@ const NoticeTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -305,7 +308,7 @@ const NoticeTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -316,7 +319,7 @@ const NoticeTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -227,8 +227,8 @@ const OperlogTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.Monitor.Operlog> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -241,6 +241,9 @@ const OperlogTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -273,7 +276,7 @@ const OperlogTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -284,7 +287,7 @@ const OperlogTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -225,8 +225,8 @@ const PostTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.Post> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -239,6 +239,9 @@ const PostTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -271,7 +274,7 @@ const PostTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -282,7 +285,7 @@ const PostTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -163,8 +163,8 @@ const AuthUserTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | 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> | <ProTable<API.System.User> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -176,6 +176,9 @@ const AuthUserTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -208,7 +211,7 @@ const AuthUserTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="system.role.auth.cancelAll" defaultMessage="批量取消授权" /> | <FormattedMessage id="system.role.auth.cancelAll" defaultMessage="批量取消授权" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -218,8 +221,7 @@ const AuthUserTableList: React.FC = () => { | |||||
| history.back(); | history.back(); | ||||
| }} | }} | ||||
| > | > | ||||
| <RollbackOutlined /> | |||||
| <FormattedMessage id="pages.goback" defaultMessage="返回" /> | |||||
| <RollbackOutlined /> <FormattedMessage id="pages.goback" defaultMessage="返回" /> | |||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| request={(params) => | request={(params) => | ||||
| @@ -360,9 +360,9 @@ const RoleTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | return ( | ||||
| <PageContainer header={{ breadcrumb: {} }}> | |||||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||||
| {contextHolder} | {contextHolder} | ||||
| <div style={{ width: '100%', float: 'right' }}> | |||||
| <div style={{ width: '100%', height: '100%' }}> | |||||
| <ProTable<API.System.Role> | <ProTable<API.System.Role> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -375,6 +375,9 @@ const RoleTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -416,7 +419,7 @@ const RoleTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -427,7 +430,7 @@ const RoleTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -365,10 +365,10 @@ const UserTableList: React.FC = () => { | |||||
| ]; | ]; | ||||
| return ( | return ( | ||||
| <PageContainer header={{ breadcrumb: {} }}> | |||||
| <PageContainer header={{ breadcrumb: {}, title: '' }} className="system-menu"> | |||||
| {contextHolder} | {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> | <Card> | ||||
| <DeptTree | <DeptTree | ||||
| onSelect={async (value: any) => { | onSelect={async (value: any) => { | ||||
| @@ -380,7 +380,7 @@ const UserTableList: React.FC = () => { | |||||
| /> | /> | ||||
| </Card> | </Card> | ||||
| </Col> | </Col> | ||||
| <Col lg={18} md={24}> | |||||
| <Col lg={18} md={24} style={{ height: '100%' }}> | |||||
| <ProTable<API.System.User> | <ProTable<API.System.User> | ||||
| headerTitle={intl.formatMessage({ | headerTitle={intl.formatMessage({ | ||||
| id: 'pages.searchTable.title', | id: 'pages.searchTable.title', | ||||
| @@ -393,6 +393,9 @@ const UserTableList: React.FC = () => { | |||||
| search={{ | search={{ | ||||
| labelWidth: 120, | labelWidth: 120, | ||||
| }} | }} | ||||
| scroll={{ y: 'calc(100% - 55px)' }} | |||||
| tableAlertRender={false} | |||||
| tableAlertOptionRender={false} | |||||
| toolBarRender={() => [ | toolBarRender={() => [ | ||||
| <Button | <Button | ||||
| type="primary" | type="primary" | ||||
| @@ -452,7 +455,7 @@ const UserTableList: React.FC = () => { | |||||
| }); | }); | ||||
| }} | }} | ||||
| > | > | ||||
| <DeleteOutlined /> | |||||
| <DeleteOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" /> | ||||
| </Button>, | </Button>, | ||||
| <Button | <Button | ||||
| @@ -463,7 +466,7 @@ const UserTableList: React.FC = () => { | |||||
| handleExport(); | handleExport(); | ||||
| }} | }} | ||||
| > | > | ||||
| <PlusOutlined /> | |||||
| <PlusOutlined />{' '} | |||||
| <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" /> | ||||
| </Button>, | </Button>, | ||||
| ]} | ]} | ||||
| @@ -18,7 +18,7 @@ const CacheInfo: React.FC = () => { | |||||
| }); | }); | ||||
| return ( | return ( | ||||
| <div style={{}}> | |||||
| <div> | |||||
| <iframe | <iframe | ||||
| style={{ width: '100%', border: '0px', height: '100%' }} | style={{ width: '100%', border: '0px', height: '100%' }} | ||||
| src={`/api/swagger-ui/index.html`} | src={`/api/swagger-ui/index.html`} | ||||
| @@ -49,6 +49,7 @@ | |||||
| position: fixed; | position: fixed; | ||||
| right: 30px; | right: 30px; | ||||
| bottom: 20px; | bottom: 20px; | ||||
| z-index: 99; | |||||
| width: 64px; | width: 64px; | ||||
| height: 64px; | height: 64px; | ||||
| background-color: white; | background-color: white; | ||||
| @@ -71,7 +71,7 @@ function Workspace() { | |||||
| <AssetsManagement></AssetsManagement> | <AssetsManagement></AssetsManagement> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <Draggable onStart={handleStart} onStop={handleStop} onDrag={handleDrag}> | |||||
| <Draggable onStart={handleStart} onStop={handleStop} onDrag={handleDrag} bounds="body"> | |||||
| <img | <img | ||||
| className={styles['workspace__robot-img']} | className={styles['workspace__robot-img']} | ||||
| src={require('@/assets/img/robot.png')} | src={require('@/assets/img/robot.png')} | ||||
| @@ -7,10 +7,9 @@ export function getJupyterUrl() { | |||||
| } | } | ||||
| // 查询 labelStudio url | // 查询 labelStudio url | ||||
| export function getLabelStudioUrl(params: any) { | |||||
| export function getLabelStudioUrl() { | |||||
| return request(`/api/mmp/labelStudio/getURL`, { | return request(`/api/mmp/labelStudio/getURL`, { | ||||
| method: 'GET', | method: 'GET', | ||||
| params, | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -2,7 +2,7 @@ import { MenuDataItem } from '@ant-design/pro-components'; | |||||
| import { request } from '@umijs/max'; | import { request } from '@umijs/max'; | ||||
| import React, { lazy } from 'react'; | import React, { lazy } from 'react'; | ||||
| let remoteMenu: any = []; | |||||
| let remoteMenu: any = null; | |||||
| export function getRemoteMenu() { | export function getRemoteMenu() { | ||||
| return remoteMenu; | return remoteMenu; | ||||
| @@ -12,30 +12,35 @@ export function setRemoteMenu(data: any) { | |||||
| remoteMenu = data; | 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) { | function patchRouteItems(route: any, menu: any, parentPath: string) { | ||||
| for (const menuItem of menu) { | for (const menuItem of menu) { | ||||
| if (menuItem.component === 'Layout' || menuItem.component === 'ParentView') { | if (menuItem.component === 'Layout' || menuItem.component === 'ParentView') { | ||||
| if (menuItem.routes) { | 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 = { | newItem = { | ||||
| path: menuItem.path, | path: menuItem.path, | ||||
| routes: [], | routes: [], | ||||
| children: [], | |||||
| }; | }; | ||||
| route.children = route.routes; | |||||
| route.routes.push(newItem); | route.routes.push(newItem); | ||||
| } | } | ||||
| patchRouteItems(newItem, menuItem.routes, parentPath + menuItem.path + '/'); | patchRouteItems(newItem, menuItem.routes, parentPath + menuItem.path + '/'); | ||||
| } | } | ||||
| } else { | } else { | ||||
| if (getLocalRoute(route, menuItem)) { | |||||
| return; | |||||
| } | |||||
| const names: string[] = menuItem.component.split('/'); | const names: string[] = menuItem.component.split('/'); | ||||
| let path = ''; | let path = ''; | ||||
| names.forEach((name) => { | names.forEach((name) => { | ||||
| @@ -53,17 +58,13 @@ function patchRouteItems(route: any, menu: any, parentPath: string) { | |||||
| } | } | ||||
| if (route.routes === undefined) { | if (route.routes === undefined) { | ||||
| route.routes = []; | route.routes = []; | ||||
| route.children = route.routes; | |||||
| } | } | ||||
| if (route.children === undefined) { | |||||
| route.children = []; | |||||
| } | |||||
| const newRoute = { | const newRoute = { | ||||
| element: React.createElement(lazy(() => import('@/pages/' + path))), | element: React.createElement(lazy(() => import('@/pages/' + path))), | ||||
| path: parentPath + menuItem.path, | path: parentPath + menuItem.path, | ||||
| }; | }; | ||||
| // console.log(newRoute); | |||||
| route.children.push(newRoute); | |||||
| route.routes.push(newRoute); | route.routes.push(newRoute); | ||||
| } | } | ||||
| } | } | ||||