Browse Source

Merge pull request '合并dev' (#112) from dev into master

dev-lhz
cp3hnu 1 year ago
parent
commit
1b9369bf24
33 changed files with 535 additions and 165 deletions
  1. +4
    -4
      react-ui/config/proxy.ts
  2. +15
    -15
      react-ui/config/routes.ts
  3. +2
    -1
      react-ui/src/app.tsx
  4. BIN
      react-ui/src/assets/img/robot.png
  5. +2
    -2
      react-ui/src/components/FullScreenFrame/index.less
  6. +18
    -0
      react-ui/src/components/FullScreenFrame/index.tsx
  7. +32
    -0
      react-ui/src/components/MenuIconSelector/index.less
  8. +62
    -0
      react-ui/src/components/MenuIconSelector/index.tsx
  9. +163
    -0
      react-ui/src/iconfont/iconfont.json
  10. +56
    -0
      react-ui/src/overrides.less
  11. +9
    -0
      react-ui/src/pages/Application/index.tsx
  12. +2
    -6
      react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx
  13. +5
    -2
      react-ui/src/pages/Experiment/Comparison/index.tsx
  14. +7
    -4
      react-ui/src/pages/Monitor/Job/index.tsx
  15. +7
    -4
      react-ui/src/pages/Monitor/JobLog/index.tsx
  16. +7
    -4
      react-ui/src/pages/System/Config/index.tsx
  17. +7
    -4
      react-ui/src/pages/System/Dept/index.tsx
  18. +7
    -4
      react-ui/src/pages/System/Dict/index.tsx
  19. +7
    -4
      react-ui/src/pages/System/DictData/index.tsx
  20. +9
    -6
      react-ui/src/pages/System/Logininfor/index.tsx
  21. +40
    -52
      react-ui/src/pages/System/Menu/edit.tsx
  22. +7
    -4
      react-ui/src/pages/System/Menu/index.tsx
  23. +7
    -4
      react-ui/src/pages/System/Notice/index.tsx
  24. +7
    -4
      react-ui/src/pages/System/Operlog/index.tsx
  25. +7
    -4
      react-ui/src/pages/System/Post/index.tsx
  26. +7
    -5
      react-ui/src/pages/System/Role/authUser.tsx
  27. +7
    -4
      react-ui/src/pages/System/Role/index.tsx
  28. +9
    -6
      react-ui/src/pages/System/User/index.tsx
  29. +1
    -1
      react-ui/src/pages/Tool/Swagger/index.tsx
  30. +1
    -0
      react-ui/src/pages/Workspace/index.less
  31. +1
    -1
      react-ui/src/pages/Workspace/index.tsx
  32. +1
    -2
      react-ui/src/services/developmentEnvironment/index.ts
  33. +19
    -18
      react-ui/src/services/session.ts

+ 4
- 4
react-ui/config/proxy.ts View File

@@ -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,
},
},


+ 15
- 15
react-ui/config/routes.ts View File

@@ -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',
},
],


+ 2
- 1
react-ui/src/app.tsx View File

@@ -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 = {};


BIN
react-ui/src/assets/img/robot.png View File

Before After
Width: 128  |  Height: 128  |  Size: 1.8 kB Width: 128  |  Height: 128  |  Size: 1.8 kB

react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.less → react-ui/src/components/FullScreenFrame/index.less View File

@@ -1,8 +1,8 @@
.container {
.kf-full-screen-frame {
width: 100%;
height: 100%;

.frame {
&__iframe {
width: 100%;
height: 100%;
border: none;

+ 18
- 0
react-ui/src/components/FullScreenFrame/index.tsx View File

@@ -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;

+ 32
- 0
react-ui/src/components/MenuIconSelector/index.less View File

@@ -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;
}
}
}

+ 62
- 0
react-ui/src/components/MenuIconSelector/index.tsx View File

@@ -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;

+ 163
- 0
react-ui/src/iconfont/iconfont.json View File

@@ -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
}
]
}

+ 56
- 0
react-ui/src/overrides.less View File

@@ -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%;
}
}
}
}
}
}
}
}
}
}
}
}
}

+ 9
- 0
react-ui/src/pages/Application/index.tsx View File

@@ -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;

+ 2
- 6
react-ui/src/pages/DatasetPreparation/DatasetAnnotation/index.tsx View File

@@ -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;

+ 5
- 2
react-ui/src/pages/Experiment/Comparison/index.tsx View File

@@ -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,
})),
},
];


+ 7
- 4
react-ui/src/pages/Monitor/Job/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/Monitor/JobLog/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/System/Config/index.tsx View File

@@ -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


+ 7
- 4
react-ui/src/pages/System/Dept/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/System/Dict/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/System/DictData/index.tsx View File

@@ -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>,
]}


+ 9
- 6
react-ui/src/pages/System/Logininfor/index.tsx View File

@@ -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>,
]}


+ 40
- 52
react-ui/src/pages/System/Menu/edit.tsx View File

@@ -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>
);
};


+ 7
- 4
react-ui/src/pages/System/Menu/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/System/Notice/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/System/Operlog/index.tsx View File

@@ -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>,
]}


+ 7
- 4
react-ui/src/pages/System/Post/index.tsx View File

@@ -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>,
]}


+ 7
- 5
react-ui/src/pages/System/Role/authUser.tsx View File

@@ -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) =>


+ 7
- 4
react-ui/src/pages/System/Role/index.tsx View File

@@ -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>,
]}


+ 9
- 6
react-ui/src/pages/System/User/index.tsx View File

@@ -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>,
]}


+ 1
- 1
react-ui/src/pages/Tool/Swagger/index.tsx View File

@@ -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`}


+ 1
- 0
react-ui/src/pages/Workspace/index.less View File

@@ -49,6 +49,7 @@
position: fixed;
right: 30px;
bottom: 20px;
z-index: 99;
width: 64px;
height: 64px;
background-color: white;


+ 1
- 1
react-ui/src/pages/Workspace/index.tsx View File

@@ -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')}


+ 1
- 2
react-ui/src/services/developmentEnvironment/index.ts View File

@@ -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,
});
}



+ 19
- 18
react-ui/src/services/session.ts View File

@@ -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);
}
}


Loading…
Cancel
Save