Browse Source

fix: 修改菜单管理新建bug

pull/111/head
cp3hnu 1 year ago
parent
commit
fab65e2dd5
5 changed files with 299 additions and 54 deletions
  1. +2
    -2
      react-ui/src/app.tsx
  2. +32
    -0
      react-ui/src/components/MenuIconSelector/index.less
  3. +62
    -0
      react-ui/src/components/MenuIconSelector/index.tsx
  4. +163
    -0
      react-ui/src/iconfont/iconfont.json
  5. +40
    -52
      react-ui/src/pages/System/Menu/edit.tsx

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

@@ -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();
@@ -193,7 +193,6 @@ export function render(oldRender: () => void) {
oldRender(); oldRender();
}) })
.catch(() => { .catch(() => {
setRemoteMenu([]);
oldRender(); oldRender();
}); });
} }
@@ -208,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 = {};


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

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

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


Loading…
Cancel
Save