update 强化菜单
This commit is contained in:
@@ -7,29 +7,31 @@ import { api } from 'common/api'
|
||||
import { EMPTY_ID } from 'util/global'
|
||||
|
||||
const initialValues = {
|
||||
type: '1',
|
||||
openType: '1',
|
||||
type: 1,
|
||||
openType: 1,
|
||||
weight: '2',
|
||||
visible: true,
|
||||
sort: 100
|
||||
sort: 100,
|
||||
}
|
||||
|
||||
export default class form extends Component {
|
||||
|
||||
state = {
|
||||
// 加载状态
|
||||
loading: true,
|
||||
codes: {
|
||||
menuType: [],
|
||||
openType: []
|
||||
openType: [],
|
||||
menuWeight: [],
|
||||
},
|
||||
options: {
|
||||
appList: [],
|
||||
parentTreeData: []
|
||||
parentTreeData: [],
|
||||
},
|
||||
|
||||
addType: [],
|
||||
type: initialValues.type,
|
||||
openType: initialValues.openType,
|
||||
icon: ''
|
||||
icon: '',
|
||||
}
|
||||
|
||||
// 表单实例
|
||||
@@ -51,45 +53,49 @@ export default class form extends Component {
|
||||
* 填充数据
|
||||
* 可以在设置this.record之后对其作出数据结构调整
|
||||
* [异步,必要]
|
||||
* @param {*} params
|
||||
* @param {*} params
|
||||
*/
|
||||
async fillData(params) {
|
||||
const form = this.form.current
|
||||
this.record = cloneDeep(params.record)
|
||||
//#region 从后端转换成前段所需格式
|
||||
const { menuType, openType } = await getDictData('menu_type', 'open_type')
|
||||
const codes = await getDictData('menu_type', 'open_type', 'menu_weight')
|
||||
const appList = await this.onLoadSysApplist()
|
||||
let parentTreeData = []
|
||||
if (params.isParent) {
|
||||
parentTreeData = await this.onLoadMenuTree(params.parent.application)
|
||||
} else if (params.record) {
|
||||
}
|
||||
|
||||
if (params.record) {
|
||||
parentTreeData = await this.onLoadMenuTree(params.record.application)
|
||||
} else {
|
||||
this.setState({ addType: params.addType })
|
||||
if (params.addType.length) {
|
||||
form.setFieldsValue({
|
||||
type: params.addType[0],
|
||||
})
|
||||
}
|
||||
}
|
||||
const icon = params.record && params.record.icon
|
||||
this.setState({
|
||||
codes: {
|
||||
menuType,
|
||||
openType
|
||||
},
|
||||
codes,
|
||||
options: {
|
||||
appList,
|
||||
parentTreeData
|
||||
parentTreeData,
|
||||
},
|
||||
icon
|
||||
icon,
|
||||
})
|
||||
//#endregion
|
||||
const form = this.form.current
|
||||
if (params.isParent) {
|
||||
form.setFieldsValue({
|
||||
pid: params.parent.id,
|
||||
application: params.parent.application
|
||||
application: params.parent.application,
|
||||
})
|
||||
} else {
|
||||
form.setFieldsValue(this.record)
|
||||
}
|
||||
|
||||
this.setState({
|
||||
loading: false
|
||||
})
|
||||
this.setState({ loading: false })
|
||||
|
||||
this.onTypeChange()
|
||||
}
|
||||
@@ -98,7 +104,7 @@ export default class form extends Component {
|
||||
* 获取数据
|
||||
* 可以对postData进行数据结构调整
|
||||
* [异步,必要]
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
async getData() {
|
||||
const form = this.form.current
|
||||
@@ -123,30 +129,31 @@ export default class form extends Component {
|
||||
|
||||
async onLoadMenuTree(application) {
|
||||
const { data } = await api.getMenuTree({ application })
|
||||
return [{
|
||||
id: EMPTY_ID,
|
||||
parentId: undefined,
|
||||
title: '顶级',
|
||||
value: EMPTY_ID,
|
||||
pid: undefined,
|
||||
children: data,
|
||||
}]
|
||||
return [
|
||||
{
|
||||
id: EMPTY_ID,
|
||||
parentId: undefined,
|
||||
title: '顶级',
|
||||
value: EMPTY_ID,
|
||||
pid: undefined,
|
||||
children: data,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
onTypeChange() {
|
||||
this.onTypeChangeGroup()
|
||||
const form = this.form.current
|
||||
const { type } = form.getFieldsValue()
|
||||
if (['0', '2'].includes(type)) {
|
||||
form.setFieldsValue({
|
||||
openType: '0'
|
||||
})
|
||||
} else {
|
||||
form.setFieldsValue({
|
||||
openType: '1'
|
||||
})
|
||||
}
|
||||
// const form = this.form.current
|
||||
// const { type } = form.getFieldsValue()
|
||||
// if ([0, 2].includes(type)) {
|
||||
// form.setFieldsValue({
|
||||
// openType: 0,
|
||||
// })
|
||||
// } else {
|
||||
// form.setFieldsValue({
|
||||
// openType: 1,
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
onOpenTypeChange() {
|
||||
@@ -168,178 +175,221 @@ export default class form extends Component {
|
||||
|
||||
this.setState({
|
||||
type,
|
||||
openType
|
||||
openType,
|
||||
})
|
||||
}
|
||||
|
||||
async onApplicationChange(value) {
|
||||
this.setState({
|
||||
loading: true
|
||||
loading: true,
|
||||
})
|
||||
const parentTreeData = await this.onLoadMenuTree(value)
|
||||
this.setState({
|
||||
loading: false,
|
||||
options: {
|
||||
...this.state.options,
|
||||
parentTreeData
|
||||
}
|
||||
parentTreeData,
|
||||
},
|
||||
})
|
||||
this.form.current.setFieldsValue({
|
||||
pid: undefined
|
||||
pid: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
onSelectIcon(icon) {
|
||||
this.form.current.setFieldsValue({
|
||||
icon
|
||||
icon,
|
||||
})
|
||||
this.setState({ icon })
|
||||
}
|
||||
//#endregion
|
||||
|
||||
render() {
|
||||
const { loading, codes, options, addType, type, openType, icon } = this.state
|
||||
|
||||
return (
|
||||
<Form
|
||||
initialValues={initialValues}
|
||||
ref={this.form}
|
||||
className="yo-form"
|
||||
>
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
||||
<Form initialValues={initialValues} ref={this.form} className="yo-form">
|
||||
<Spin spinning={loading} indicator={<AntIcon type="loading" />}>
|
||||
<div className="yo-form-group">
|
||||
<h3 className="h3">基本信息</h3>
|
||||
<div className="yo-form-group">
|
||||
<Form.Item
|
||||
label="菜单类型"
|
||||
name="type"
|
||||
help={
|
||||
tooltip={
|
||||
<>
|
||||
目录:默认添加在顶级
|
||||
<br />菜单:
|
||||
<br />按钮:
|
||||
目录:一级菜单,默认添加在顶级
|
||||
<br />
|
||||
菜单:二级菜单
|
||||
<br />
|
||||
按钮:菜单中对应到接口的功能
|
||||
</>
|
||||
}
|
||||
rules={[{ required: true, message: '请选择菜单类型' }]}
|
||||
>
|
||||
<Radio.Group onChange={(e) => this.onTypeChange(e)}>
|
||||
{
|
||||
this.state.codes.menuType.map(item => {
|
||||
return (
|
||||
<Radio.Button
|
||||
key={item.code}
|
||||
value={item.code}
|
||||
>{item.value}</Radio.Button>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Radio.Group onChange={e => this.onTypeChange(e)}>
|
||||
{codes.menuType.map(item => {
|
||||
return (
|
||||
<Radio.Button
|
||||
key={item.code}
|
||||
value={+item.code}
|
||||
disabled={!addType.includes(+item.code)}
|
||||
>
|
||||
{item.value}
|
||||
</Radio.Button>
|
||||
)
|
||||
})}
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item label="名称" name="name" rules={[{ required: true, message: '请输入名称' }]}>
|
||||
<Form.Item
|
||||
label="名称"
|
||||
name="name"
|
||||
rules={[{ required: true, message: '请输入名称' }]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入名称" />
|
||||
</Form.Item>
|
||||
<Form.Item label="唯一编码" name="code">
|
||||
<Input autoComplete="off" placeholder="请输入唯一编码" />
|
||||
</Form.Item>
|
||||
<Form.Item label="所属应用" name="application" rules={[{ required: true, message: '请选择所属应用' }]}>
|
||||
<Select placeholder="请选择所属应用" onChange={(value) => this.onApplicationChange(value)}>
|
||||
{
|
||||
this.state.options.appList.map(item => {
|
||||
return (
|
||||
<Select.Option
|
||||
key={item.code}
|
||||
value={item.code}
|
||||
>{item.name}</Select.Option>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Form.Item
|
||||
label="所属应用"
|
||||
name="application"
|
||||
rules={[{ required: true, message: '请选择所属应用' }]}
|
||||
>
|
||||
<Select
|
||||
placeholder="请选择所属应用"
|
||||
onChange={value => this.onApplicationChange(value)}
|
||||
>
|
||||
{options.appList.map(item => {
|
||||
return (
|
||||
<Select.Option key={item.code} value={item.code}>
|
||||
{item.name}
|
||||
</Select.Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{
|
||||
this.state.type != 0 &&
|
||||
<Form.Item label="父级菜单" name="pid" rules={[{ required: true, message: '请选择父级' }]}>
|
||||
{type != 0 && (
|
||||
<Form.Item
|
||||
label="父级菜单"
|
||||
name="pid"
|
||||
rules={[{ required: true, message: '请选择父级' }]}
|
||||
>
|
||||
<TreeSelect
|
||||
dropdownStyle={{ maxHeight: '300px', overflow: 'auto' }}
|
||||
treeData={this.state.options.parentTreeData}
|
||||
treeData={options.parentTreeData}
|
||||
placeholder="请选择父级菜单"
|
||||
/>
|
||||
</Form.Item>
|
||||
}
|
||||
)}
|
||||
<Form.Item
|
||||
label="权重"
|
||||
name="weight"
|
||||
tooltip={
|
||||
<>
|
||||
系统权重:菜单/功能任何角色可用
|
||||
<br />
|
||||
业务权重:菜单/功能为超级管理员不可用,可防止管理员误操作
|
||||
</>
|
||||
}
|
||||
rules={[{ required: true, message: '请选择权重' }]}
|
||||
>
|
||||
<Radio.Group>
|
||||
{codes.menuWeight.map(item => {
|
||||
return (
|
||||
<Radio.Button key={item.code} value={item.code}>
|
||||
{item.value}
|
||||
</Radio.Button>
|
||||
)
|
||||
})}
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</div>
|
||||
<h3 className="h3">扩展信息</h3>
|
||||
<div className="yo-form-group">
|
||||
{
|
||||
this.state.type == 1 &&
|
||||
{type == 1 && (
|
||||
<Form.Item label="打开方式" name="openType">
|
||||
<Radio.Group onChange={(e) => this.onOpenTypeChange(e)}>
|
||||
{
|
||||
this.state.codes.openType.map(item => {
|
||||
return (
|
||||
<Radio.Button
|
||||
key={item.code}
|
||||
value={item.code}
|
||||
>{item.value}</Radio.Button>
|
||||
)
|
||||
})
|
||||
}
|
||||
<Radio.Group onChange={e => this.onOpenTypeChange(e)}>
|
||||
{codes.openType.map(item => {
|
||||
return (
|
||||
<Radio.Button key={item.code} value={+item.code}>
|
||||
{item.value}
|
||||
</Radio.Button>
|
||||
)
|
||||
})}
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
this.state.type == 1 && this.state.openType == 1 &&
|
||||
<Form.Item label="前端组件" name="component" rules={[{ required: true, message: '请输入前端组件' }]}>
|
||||
)}
|
||||
{type == 1 && openType == 1 && (
|
||||
<Form.Item
|
||||
label="前端组件"
|
||||
name="component"
|
||||
tooltip="打开新页签并渲染前端组件"
|
||||
rules={[{ required: true, message: '请输入前端组件' }]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入前端组件" />
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
this.state.type == 1 && this.state.openType == 2 &&
|
||||
<Form.Item label="内链地址" name="router" rules={[{ required: true, message: '请输入内链地址' }]}>
|
||||
)}
|
||||
{type == 1 && openType == 2 && (
|
||||
<Form.Item
|
||||
label="内链地址"
|
||||
name="link"
|
||||
tooltip="打开新页签并使用iframe加载页面"
|
||||
rules={[{ required: true, message: '请输入内链地址' }]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入内链地址" />
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
this.state.type == 1 && this.state.openType == 3 &&
|
||||
<Form.Item label="外链地址" name="link" rules={[{ required: true, message: '请输入外链地址' }]}>
|
||||
)}
|
||||
{type == 1 && openType == 3 && (
|
||||
<Form.Item
|
||||
label="外链地址"
|
||||
name="redirect"
|
||||
tooltip="打开新的浏览器窗口"
|
||||
rules={[{ required: true, message: '请输入外链地址' }]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入外链地址" />
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
this.state.type == 2 &&
|
||||
<Form.Item label="权限标识" name="permission" rules={[{ required: true, message: '请输入权限标识' }]}>
|
||||
)}
|
||||
{type == 2 && (
|
||||
<Form.Item
|
||||
label="权限标识"
|
||||
name="permission"
|
||||
rules={[{ required: true, message: '请输入权限标识' }]}
|
||||
>
|
||||
<Input autoComplete="off" placeholder="请输入权限标识" />
|
||||
</Form.Item>
|
||||
}
|
||||
{
|
||||
this.state.type == 2 &&
|
||||
<Form.Item label="关联上级菜单显示" name="visibleParent" valuePropName="checked">
|
||||
)}
|
||||
{type == 2 && (
|
||||
<Form.Item
|
||||
label="关联上级菜单显示"
|
||||
name="visibleParent"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
}
|
||||
)}
|
||||
<Form.Item label="可见性" name="visible" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
{
|
||||
this.state.type != 2 &&
|
||||
{type != 2 && (
|
||||
<Form.Item label="图标" name="icon">
|
||||
<Input
|
||||
disabled
|
||||
placeholder="请选择图标"
|
||||
addonBefore={
|
||||
this.state.icon &&
|
||||
<AntIcon type={this.state.icon} />
|
||||
}
|
||||
addonBefore={icon && <AntIcon type={icon} />}
|
||||
addonAfter={
|
||||
<AntIcon
|
||||
type="setting"
|
||||
onClick={() =>
|
||||
this
|
||||
.iconSelector
|
||||
.current
|
||||
.open(this.form.current.getFieldValue('icon'))
|
||||
this.iconSelector.current.open(
|
||||
this.form.current.getFieldValue('icon')
|
||||
)
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
}
|
||||
)}
|
||||
<Form.Item label="排序" name="sort">
|
||||
<InputNumber
|
||||
max={1000}
|
||||
@@ -355,7 +405,7 @@ export default class form extends Component {
|
||||
</div>
|
||||
</Spin>
|
||||
|
||||
<IconSelector ref={this.iconSelector} onSelect={(icon) => this.onSelectIcon(icon)} />
|
||||
<IconSelector ref={this.iconSelector} onSelect={icon => this.onSelectIcon(icon)} />
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Button, Table, Card, Popconfirm, message as Message, Row, Col, Tooltip } from 'antd'
|
||||
import { Button, Table, Card, Popconfirm, message as Message, Row, Col, Tooltip, Tag } from 'antd'
|
||||
import { isEqual } from 'lodash'
|
||||
import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions } from 'components'
|
||||
import { api } from 'common/api'
|
||||
@@ -24,6 +24,7 @@ export default class index extends Component {
|
||||
codes: {
|
||||
menuType: [],
|
||||
menuWeight: [],
|
||||
openType: [],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -55,9 +56,36 @@ export default class index extends Component {
|
||||
render: text => text && <AntIcon type={text} />,
|
||||
},
|
||||
{
|
||||
title: '前端组件',
|
||||
title: '连接',
|
||||
width: 220,
|
||||
dataIndex: 'component',
|
||||
dataIndex: 'openType',
|
||||
render: (text, record) => {
|
||||
switch (text) {
|
||||
case 1:
|
||||
return (
|
||||
<>
|
||||
<Tag color="green">{this.bindCodeValue(text, 'open_type')}</Tag>{' '}
|
||||
{record.component}
|
||||
</>
|
||||
)
|
||||
case 2:
|
||||
return (
|
||||
<>
|
||||
<Tag color="orange">{this.bindCodeValue(text, 'open_type')}</Tag>{' '}
|
||||
{record.link}
|
||||
</>
|
||||
)
|
||||
case 3:
|
||||
return (
|
||||
<>
|
||||
<Tag color="red">{this.bindCodeValue(text, 'open_type')}</Tag>{' '}
|
||||
{record.redirect}
|
||||
</>
|
||||
)
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
@@ -83,7 +111,9 @@ export default class index extends Component {
|
||||
render: (text, record) => (
|
||||
<QueryTableActions>
|
||||
<Auth auth="sysMenu:edit">
|
||||
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
|
||||
<a onClick={() => this.onOpen({ modal: this.editForm, record })}>
|
||||
编辑
|
||||
</a>
|
||||
</Auth>
|
||||
<Auth auth="sysMenu:delete">
|
||||
<Popconfirm
|
||||
@@ -96,7 +126,16 @@ export default class index extends Component {
|
||||
</Auth>
|
||||
{record.type < 2 && (
|
||||
<Auth auth="sysMenu:add">
|
||||
<a onClick={() => this.onOpen(this.addForm, record, true)}>
|
||||
<a
|
||||
onClick={() =>
|
||||
this.onOpen({
|
||||
modal: this.addForm,
|
||||
record,
|
||||
isParent: true,
|
||||
addType: record.type == 0 ? [1] : [2],
|
||||
})
|
||||
}
|
||||
>
|
||||
{record.type == 0 ? '新增子菜单' : '新增功能'}
|
||||
</a>
|
||||
</Auth>
|
||||
@@ -125,7 +164,7 @@ export default class index extends Component {
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.table.current.onLoading()
|
||||
getDictData('menu_type', 'menu_weight').then(res => {
|
||||
getDictData('menu_type', 'menu_weight', 'open_type').then(res => {
|
||||
this.setState(
|
||||
{
|
||||
codes: res,
|
||||
@@ -162,7 +201,7 @@ export default class index extends Component {
|
||||
name = toCamelCase(name)
|
||||
const codes = this.state.codes[name]
|
||||
if (codes) {
|
||||
const c = codes.find(p => p.code === code)
|
||||
const c = codes.find(p => p.code == code)
|
||||
if (c) {
|
||||
return c.value
|
||||
}
|
||||
@@ -175,15 +214,17 @@ export default class index extends Component {
|
||||
* @param {*} modal
|
||||
* @param {*} record
|
||||
*/
|
||||
onOpen(modal, record, isParent = false) {
|
||||
onOpen({ modal, record, isParent = false, addType = [] }) {
|
||||
const params = isParent
|
||||
? {
|
||||
parent: record,
|
||||
isParent,
|
||||
addType,
|
||||
}
|
||||
: {
|
||||
record,
|
||||
isParent,
|
||||
addType,
|
||||
}
|
||||
|
||||
modal.current.open(params)
|
||||
@@ -246,7 +287,9 @@ export default class index extends Component {
|
||||
<Tooltip title="编辑">
|
||||
<a
|
||||
className="link-gray"
|
||||
onClick={() => this.onOpen(this.editForm, item)}
|
||||
onClick={() =>
|
||||
this.onOpen({ modal: this.editForm, record: item })
|
||||
}
|
||||
>
|
||||
<AntIcon type="edit" />
|
||||
</a>
|
||||
@@ -280,9 +323,12 @@ export default class index extends Component {
|
||||
if (isFunction) {
|
||||
grids.push(
|
||||
<Card.Grid
|
||||
key={0}
|
||||
style={{ padding: '18px 12px', cursor: 'pointer' }}
|
||||
className="text-center"
|
||||
onClick={() => this.onOpen(this.addForm, record, true)}
|
||||
onClick={() =>
|
||||
this.onOpen({ modal: this.addForm, record, isParent: true, addType: [2] })
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<AntIcon type="plus" className="text-normal h2" />
|
||||
@@ -331,9 +377,11 @@ export default class index extends Component {
|
||||
<Auth auth="sysMenu:add">
|
||||
<Button
|
||||
icon={<AntIcon type="plus" />}
|
||||
onClick={() => this.onOpen(this.addForm)}
|
||||
onClick={() =>
|
||||
this.onOpen({ modal: this.addForm, addType: [0, 1] })
|
||||
}
|
||||
>
|
||||
新增{name}
|
||||
新增目录/菜单
|
||||
</Button>
|
||||
</Auth>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user