You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
6.2 KiB
175 lines
6.2 KiB
import { useTranslation } from '@/i18n.ts'
|
|
import { PageContainer, ProCard } from '@ant-design/pro-components'
|
|
import { Button, Form, Input, message, Radio, TreeSelect, InputNumber, notification } from 'antd'
|
|
import { useAtomValue } from 'jotai'
|
|
import { menuDataAtom, saveOrUpdateMenuAtom, selectedMenuAtom } from './store.ts'
|
|
import IconPicker from '@/components/icon/picker'
|
|
import ButtonTable from './components/ButtonTable.tsx'
|
|
import { Flexbox } from 'react-layout-kit'
|
|
import { DraggablePanel } from '@/components/draggable-panel'
|
|
import { useStyle } from './style.ts'
|
|
import { MenuItem } from '@/types'
|
|
import MenuTree from './components/MenuTree.tsx'
|
|
import BatchButton from '@/pages/system/menus/components/BatchButton.tsx'
|
|
import { useEffect } from 'react'
|
|
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
|
|
|
|
const Menus = () => {
|
|
|
|
const { styles } = useStyle()
|
|
const { t } = useTranslation()
|
|
const [ form ] = Form.useForm()
|
|
const { mutate, isPending, isSuccess, error, isError } = useAtomValue(saveOrUpdateMenuAtom)
|
|
const { data = [] } = useAtomValue(menuDataAtom)
|
|
const currentMenu = useAtomValue<MenuItem>(selectedMenuAtom) ?? {}
|
|
|
|
useEffect(() => {
|
|
if (isSuccess) {
|
|
message.success(t('saveSuccess', '保存成功'))
|
|
}
|
|
|
|
if (isError) {
|
|
notification.error({
|
|
message: t('errorTitle', '错误'),
|
|
description: (error as any).message ?? t('saveFail', '保存失败'),
|
|
})
|
|
}
|
|
|
|
}, [ isError, isSuccess ])
|
|
|
|
return (
|
|
<PageContainer breadcrumbRender={false} title={false} className={styles.container}>
|
|
|
|
<Flexbox horizontal>
|
|
<DraggablePanel expandable={false}
|
|
placement="left"
|
|
defaultSize={{ width: 300 }}
|
|
maxWidth={500}
|
|
>
|
|
<ProCard title={t('system.menus.title', '菜单')}
|
|
extra={
|
|
<BatchButton/>
|
|
}
|
|
>
|
|
<MenuTree form={form}/>
|
|
|
|
</ProCard>
|
|
</DraggablePanel>
|
|
<Flexbox className={styles.box}>
|
|
|
|
<Form form={form}
|
|
initialValues={currentMenu!}
|
|
labelCol={{ flex: '110px' }}
|
|
labelAlign="left"
|
|
labelWrap
|
|
wrapperCol={{ flex: 1 }}
|
|
colon={false}
|
|
className={styles.form}
|
|
>
|
|
|
|
<ProCard title={t('system.menus.setting', '配置')}
|
|
className={styles.formSetting}
|
|
>
|
|
|
|
<Form.Item hidden={true} label={'id'} name={'id'}>
|
|
<Input disabled={true}/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.title', '菜单名称')} name={'title'}>
|
|
<Input/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.parent', '上级菜单')} name={'parent_id'}>
|
|
<TreeSelect
|
|
treeData={[
|
|
{ id: 0, title: '顶级菜单', children: data as any },
|
|
]}
|
|
treeDefaultExpandAll={true}
|
|
fieldNames={{
|
|
label: 'title',
|
|
value: 'id'
|
|
}}/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.type', '类型')} name={'type'}>
|
|
<Radio.Group
|
|
options={[
|
|
{
|
|
label: t('system.menus.form.typeOptions.menu', '菜单'),
|
|
value: 'menu'
|
|
},
|
|
{
|
|
label: t('system.menus.form.typeOptions.iframe', 'iframe'),
|
|
value: 'iframe'
|
|
},
|
|
{
|
|
label: t('system.menus.form.typeOptions.link', '外链'),
|
|
value: 'link'
|
|
},
|
|
{
|
|
label: t('system.menus.form.typeOptions.button', '按钮'),
|
|
value: 'button'
|
|
},
|
|
]}
|
|
optionType="button"
|
|
buttonStyle="solid"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.name', '别名')} name={'name'}>
|
|
<Input/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.icon', '图标')} name={'icon'}>
|
|
<IconPicker placement={'left'}/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.sort', '排序')} name={'sort'}>
|
|
<InputNumber/>
|
|
</Form.Item>
|
|
<Form.Item label={t('system.menus.form.path', '路由')} name={'path'}>
|
|
<Input/>
|
|
</Form.Item>
|
|
|
|
<Form.Item label={t('system.menus.form.component', '视图')}
|
|
name={'component'}
|
|
help={t('system.menus.form.component.componentHelp', '视图路径,相对于src/pages')}
|
|
>
|
|
<Input addonBefore={'pages/'}/>
|
|
</Form.Item>
|
|
<Form.Item label={' '}>
|
|
<Button type="primary"
|
|
htmlType={'submit'}
|
|
loading={isPending}
|
|
onClick={() => {
|
|
form.validateFields().then((values) => {
|
|
mutate(values)
|
|
})
|
|
}}
|
|
>
|
|
{t('system.menus.form.save', '保存')}
|
|
</Button>
|
|
</Form.Item>
|
|
|
|
|
|
</ProCard>
|
|
<ProCard title={t('system.menus.form.button', '按钮')}
|
|
className={styles.formButtons}
|
|
colSpan={8}>
|
|
<Form.Item noStyle={true} name={'button'}
|
|
shouldUpdate={(prevValues: MenuItem, curValues) => {
|
|
return prevValues.id !== curValues.id
|
|
}}>
|
|
<ButtonTable form={form} key={(currentMenu as any).id}/>
|
|
</Form.Item>
|
|
|
|
</ProCard>
|
|
</Form>
|
|
|
|
</Flexbox>
|
|
</Flexbox>
|
|
</PageContainer>
|
|
)
|
|
}
|
|
|
|
export const Route = createLazyFileRoute('/system/menus')({
|
|
component: Menus
|
|
})
|
|
|
|
|
|
export default Menus
|