|
@ -1,9 +1,10 @@ |
|
|
import Glass from '@/components/glass' |
|
|
import Glass from '@/components/glass' |
|
|
import { useTranslation } from '@/i18n.ts' |
|
|
import { useTranslation } from '@/i18n.ts' |
|
|
|
|
|
import { PlusOutlined } from '@ant-design/icons' |
|
|
import { PageContainer, ProCard } from '@ant-design/pro-components' |
|
|
import { PageContainer, ProCard } from '@ant-design/pro-components' |
|
|
import { Button, Form, Input, Radio, TreeSelect, InputNumber, notification, Alert } from 'antd' |
|
|
|
|
|
import { useAtomValue } from 'jotai' |
|
|
|
|
|
import { menuDataAtom, saveOrUpdateMenuAtom, selectedMenuAtom } from './store.ts' |
|
|
|
|
|
|
|
|
import { Button, Form, Input, Radio, TreeSelect, InputNumber, notification, Alert, InputRef, Divider } from 'antd' |
|
|
|
|
|
import { useAtom, useAtomValue } from 'jotai' |
|
|
|
|
|
import { defaultMenu, menuDataAtom, saveOrUpdateMenuAtom, selectedMenuAtom } from './store.ts' |
|
|
import IconPicker from '@/components/icon/picker' |
|
|
import IconPicker from '@/components/icon/picker' |
|
|
import ButtonTable from './components/ButtonTable.tsx' |
|
|
import ButtonTable from './components/ButtonTable.tsx' |
|
|
import { Flexbox } from 'react-layout-kit' |
|
|
import { Flexbox } from 'react-layout-kit' |
|
@ -12,7 +13,7 @@ import { useStyle } from './style.ts' |
|
|
import { MenuItem } from '@/types' |
|
|
import { MenuItem } from '@/types' |
|
|
import MenuTree from './components/MenuTree.tsx' |
|
|
import MenuTree from './components/MenuTree.tsx' |
|
|
import BatchButton from '@/pages/system/menus/components/BatchButton.tsx' |
|
|
import BatchButton from '@/pages/system/menus/components/BatchButton.tsx' |
|
|
import { useEffect } from 'react' |
|
|
|
|
|
|
|
|
import { useEffect, useRef } from 'react' |
|
|
import { createLazyFileRoute } from '@tanstack/react-router' |
|
|
import { createLazyFileRoute } from '@tanstack/react-router' |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -23,7 +24,8 @@ const Menus = () => { |
|
|
const [ form ] = Form.useForm() |
|
|
const [ form ] = Form.useForm() |
|
|
const { mutate, isPending, isSuccess, error, isError } = useAtomValue(saveOrUpdateMenuAtom) |
|
|
const { mutate, isPending, isSuccess, error, isError } = useAtomValue(saveOrUpdateMenuAtom) |
|
|
const { data = [] } = useAtomValue(menuDataAtom) |
|
|
const { data = [] } = useAtomValue(menuDataAtom) |
|
|
const currentMenu = useAtomValue<MenuItem>(selectedMenuAtom) ?? {} |
|
|
|
|
|
|
|
|
const [ currentMenu, setMenuData ] = useAtom<MenuItem>(selectedMenuAtom) ?? {} |
|
|
|
|
|
const menuInputRef = useRef<InputRef | undefined>(undefined) |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
useEffect(() => { |
|
|
|
|
|
|
|
@ -35,6 +37,12 @@ const Menus = () => { |
|
|
} |
|
|
} |
|
|
}, [ isError, isSuccess ]) |
|
|
}, [ isError, isSuccess ]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
if (currentMenu.id === 0 && menuInputRef.current) { |
|
|
|
|
|
menuInputRef.current.focus() |
|
|
|
|
|
} |
|
|
|
|
|
}, [ currentMenu ]) |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<PageContainer breadcrumbRender={false} title={false} className={styles.container}> |
|
|
<PageContainer breadcrumbRender={false} title={false} className={styles.container}> |
|
|
|
|
|
|
|
@ -43,15 +51,33 @@ const Menus = () => { |
|
|
placement="left" |
|
|
placement="left" |
|
|
defaultSize={{ width: 300 }} |
|
|
defaultSize={{ width: 300 }} |
|
|
maxWidth={500} |
|
|
maxWidth={500} |
|
|
|
|
|
style={{ position: 'relative' }} |
|
|
> |
|
|
> |
|
|
<ProCard title={t('system.menus.title', '菜单')} |
|
|
<ProCard title={t('system.menus.title', '菜单')} |
|
|
extra={ |
|
|
extra={ |
|
|
|
|
|
<> |
|
|
<BatchButton/> |
|
|
<BatchButton/> |
|
|
|
|
|
</> |
|
|
} |
|
|
} |
|
|
> |
|
|
> |
|
|
<MenuTree form={form}/> |
|
|
<MenuTree form={form}/> |
|
|
|
|
|
|
|
|
</ProCard> |
|
|
</ProCard> |
|
|
|
|
|
<div className={styles.treeActions}> |
|
|
|
|
|
<Divider style={{ flex: 1, margin: '8px 0' }}/> |
|
|
|
|
|
<Button style={{ flex: 1 }} size={'small'} |
|
|
|
|
|
block={true} type={'dashed'} |
|
|
|
|
|
icon={<PlusOutlined/>} |
|
|
|
|
|
onClick={() => { |
|
|
|
|
|
const menu = { |
|
|
|
|
|
...defaultMenu, |
|
|
|
|
|
parent_id: 0, |
|
|
|
|
|
} |
|
|
|
|
|
setMenuData(menu) |
|
|
|
|
|
form.setFieldsValue(menu) |
|
|
|
|
|
}} |
|
|
|
|
|
>{t('actions.news')}</Button> |
|
|
|
|
|
</div> |
|
|
</DraggablePanel> |
|
|
</DraggablePanel> |
|
|
<Flexbox className={styles.box}> |
|
|
<Flexbox className={styles.box}> |
|
|
<Glass |
|
|
<Glass |
|
@ -83,8 +109,12 @@ const Menus = () => { |
|
|
<Form.Item hidden={true} label={'id'} name={'id'}> |
|
|
<Form.Item hidden={true} label={'id'} name={'id'}> |
|
|
<Input disabled={true}/> |
|
|
<Input disabled={true}/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item label={t('system.menus.form.title', '菜单名称')} name={'title'}> |
|
|
|
|
|
<Input/> |
|
|
|
|
|
|
|
|
<Form.Item |
|
|
|
|
|
rules={[ |
|
|
|
|
|
{ required: true, message: t('rules.required') } |
|
|
|
|
|
]} |
|
|
|
|
|
label={t('system.menus.form.title', '菜单名称')} name={'title'}> |
|
|
|
|
|
<Input ref={menuInputRef as any} placeholder={t('system.menus.form.title', '菜单名称')}/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item label={t('system.menus.form.parent', '上级菜单')} name={'parent_id'}> |
|
|
<Form.Item label={t('system.menus.form.parent', '上级菜单')} name={'parent_id'}> |
|
|
<TreeSelect |
|
|
<TreeSelect |
|
@ -121,8 +151,12 @@ const Menus = () => { |
|
|
buttonStyle="solid" |
|
|
buttonStyle="solid" |
|
|
/> |
|
|
/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item label={t('system.menus.form.name', '别名')} name={'name'}> |
|
|
|
|
|
<Input/> |
|
|
|
|
|
|
|
|
<Form.Item |
|
|
|
|
|
rules={[ |
|
|
|
|
|
{ required: true, message: t('rules.required') } |
|
|
|
|
|
]} |
|
|
|
|
|
label={t('system.menus.form.name', '别名')} name={'name'}> |
|
|
|
|
|
<Input placeholder={t('system.menus.form.name', '别名')}/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item label={t('system.menus.form.icon', '图标')} name={'icon'}> |
|
|
<Form.Item label={t('system.menus.form.icon', '图标')} name={'icon'}> |
|
|
<IconPicker placement={'left'}/> |
|
|
<IconPicker placement={'left'}/> |
|
|