update 强化菜单
This commit is contained in:
@@ -20,9 +20,9 @@ namespace Ewide.Core
|
|||||||
MENU = 1,
|
MENU = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按钮
|
/// 功能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Description("按钮")]
|
[Description("功能")]
|
||||||
BTN = 2
|
FUNCTION = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2417,9 +2417,9 @@
|
|||||||
菜单
|
菜单
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="F:Ewide.Core.MenuType.BTN">
|
<member name="F:Ewide.Core.MenuType.FUNCTION">
|
||||||
<summary>
|
<summary>
|
||||||
按钮
|
功能
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="T:Ewide.Core.MenuWeight">
|
<member name="T:Ewide.Core.MenuWeight">
|
||||||
@@ -4933,7 +4933,7 @@
|
|||||||
路由元信息(路由附带扩展信息)
|
路由元信息(路由附带扩展信息)
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="P:Ewide.Core.Service.AntDesignTreeNode.Path">
|
<member name="P:Ewide.Core.Service.AntDesignTreeNode.Link">
|
||||||
<summary>
|
<summary>
|
||||||
路径
|
路径
|
||||||
</summary>
|
</summary>
|
||||||
@@ -4943,6 +4943,11 @@
|
|||||||
控制路由和子路由是否显示在 sidebar
|
控制路由和子路由是否显示在 sidebar
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:Ewide.Core.Service.AntDesignTreeNode.OpenType">
|
||||||
|
<summary>
|
||||||
|
打开方式
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:Ewide.Core.Service.Meta">
|
<member name="T:Ewide.Core.Service.Meta">
|
||||||
<summary>
|
<summary>
|
||||||
路由元信息内部类
|
路由元信息内部类
|
||||||
@@ -5068,6 +5073,11 @@
|
|||||||
菜单类型(字典 0目录 1菜单 2按钮)
|
菜单类型(字典 0目录 1菜单 2按钮)
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="P:Ewide.Core.Service.AddMenuInput.OpenType">
|
||||||
|
<summary>
|
||||||
|
打开方式(字典 0无 1组件 2内链 3外链)
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="P:Ewide.Core.Service.DeleteMenuInput.Id">
|
<member name="P:Ewide.Core.Service.DeleteMenuInput.Id">
|
||||||
<summary>
|
<summary>
|
||||||
菜单Id
|
菜单Id
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace Ewide.Core
|
|||||||
OpTime = DateTime.Now,
|
OpTime = DateTime.Now,
|
||||||
Account = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_ACCOUNT)
|
Account = httpContext.User?.FindFirstValue(ClaimConst.CLAINM_ACCOUNT)
|
||||||
};
|
};
|
||||||
await sysOpLog.InsertAsync();
|
await sysOpLog.InsertNowAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,12 +38,17 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 路径
|
/// 路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Path { get; set; }
|
public string Link { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 控制路由和子路由是否显示在 sidebar
|
/// 控制路由和子路由是否显示在 sidebar
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Hidden { get; set; }
|
public bool Hidden { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打开方式
|
||||||
|
/// </summary>
|
||||||
|
public int OpenType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Ewide.Core.Service
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string Type { get; set; }
|
public virtual int Type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图标
|
/// 图标
|
||||||
@@ -55,7 +55,7 @@ namespace Ewide.Core.Service
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual string OpenType { get; set; }
|
public virtual int OpenType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否可见(Y-是,N-否)
|
/// 是否可见(Y-是,N-否)
|
||||||
@@ -99,7 +99,13 @@ namespace Ewide.Core.Service
|
|||||||
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
/// 菜单类型(字典 0目录 1菜单 2按钮)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required(ErrorMessage = "菜单类型不能为空")]
|
[Required(ErrorMessage = "菜单类型不能为空")]
|
||||||
public override string Type { get; set; }
|
public override int Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打开方式(字典 0无 1组件 2内链 3外链)
|
||||||
|
/// </summary>
|
||||||
|
[Required(ErrorMessage = "打开方式不能为空")]
|
||||||
|
public override int OpenType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeleteMenuInput
|
public class DeleteMenuInput
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace Ewide.Core.Service
|
|||||||
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
var roleIdList = await _sysUserRoleService.GetUserRoleIdList(userId);
|
||||||
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);
|
||||||
permissions = await _sysMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id))
|
permissions = await _sysMenuRep.DetachedEntities.Where(u => menuIdList.Contains(u.Id))
|
||||||
.Where(u => u.Type == (int)MenuType.BTN)
|
.Where(u => u.Type == (int)MenuType.FUNCTION)
|
||||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||||
.Select(u => u.Permission).ToListAsync();
|
.Select(u => u.Permission).ToListAsync();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -83,7 +83,7 @@ namespace Ewide.Core.Service
|
|||||||
sysMenuList = await _sysMenuRep.DetachedEntities
|
sysMenuList = await _sysMenuRep.DetachedEntities
|
||||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||||
.Where(u => u.Application == appCode)
|
.Where(u => u.Application == appCode)
|
||||||
.Where(u => u.Type != (int)MenuType.BTN)
|
.Where(u => u.Type != (int)MenuType.FUNCTION)
|
||||||
.Where(u => u.Weight != (int)MenuWeight.DEFAULT_WEIGHT)
|
.Where(u => u.Weight != (int)MenuWeight.DEFAULT_WEIGHT)
|
||||||
.OrderBy(u => u.Sort).ToListAsync();
|
.OrderBy(u => u.Sort).ToListAsync();
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ namespace Ewide.Core.Service
|
|||||||
.Where(u => menuIdList.Contains(u.Id))
|
.Where(u => menuIdList.Contains(u.Id))
|
||||||
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
.Where(u => u.Status == (int)CommonStatus.ENABLE)
|
||||||
.Where(u => u.Application == appCode)
|
.Where(u => u.Application == appCode)
|
||||||
.Where(u => u.Type != (int)MenuType.BTN)
|
.Where(u => u.Type != (int)MenuType.FUNCTION)
|
||||||
.OrderBy(u => u.Sort).ToListAsync();
|
.OrderBy(u => u.Sort).ToListAsync();
|
||||||
}
|
}
|
||||||
// 转换成登录菜单
|
// 转换成登录菜单
|
||||||
@@ -106,8 +106,9 @@ namespace Ewide.Core.Service
|
|||||||
Pid = u.Pid,
|
Pid = u.Pid,
|
||||||
Name = u.Code,
|
Name = u.Code,
|
||||||
Component = u.Component,
|
Component = u.Component,
|
||||||
Redirect = u.OpenType == (int)MenuOpenType.OUTER ? u.Link : u.Redirect,
|
Redirect = u.Redirect,
|
||||||
Path = u.OpenType == (int)MenuOpenType.OUTER ? u.Link : u.Router,
|
Link = u.Link,
|
||||||
|
OpenType = u.OpenType,
|
||||||
Meta = new Meta
|
Meta = new Meta
|
||||||
{
|
{
|
||||||
Title = u.Name,
|
Title = u.Name,
|
||||||
@@ -185,7 +186,7 @@ namespace Ewide.Core.Service
|
|||||||
/// 增加和编辑时检查参数
|
/// 增加和编辑时检查参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
private static void CheckMenuParam(MenuInput input)
|
private async Task CheckMenuParam(MenuInput input)
|
||||||
{
|
{
|
||||||
var type = input.Type;
|
var type = input.Type;
|
||||||
var router = input.Router;
|
var router = input.Router;
|
||||||
@@ -195,17 +196,17 @@ namespace Ewide.Core.Service
|
|||||||
|
|
||||||
if (type.Equals((int)MenuType.DIR))
|
if (type.Equals((int)MenuType.DIR))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(router))
|
//if (string.IsNullOrEmpty(router))
|
||||||
throw Oops.Oh(ErrorCode.D4001);
|
// throw Oops.Oh(ErrorCode.D4001);
|
||||||
}
|
}
|
||||||
else if (type.Equals((int)MenuType.MENU))
|
else if (type.Equals((int)MenuType.MENU))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(router))
|
//if (string.IsNullOrEmpty(router))
|
||||||
throw Oops.Oh(ErrorCode.D4001);
|
// throw Oops.Oh(ErrorCode.D4001);
|
||||||
if (string.IsNullOrEmpty(openType))
|
//if (string.IsNullOrEmpty(openType))
|
||||||
throw Oops.Oh(ErrorCode.D4002);
|
// throw Oops.Oh(ErrorCode.D4002);
|
||||||
}
|
}
|
||||||
else if (type.Equals((int)MenuType.BTN))
|
else if (type.Equals((int)MenuType.FUNCTION))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(permission))
|
if (string.IsNullOrEmpty(permission))
|
||||||
throw Oops.Oh(ErrorCode.D4003);
|
throw Oops.Oh(ErrorCode.D4003);
|
||||||
@@ -217,10 +218,37 @@ namespace Ewide.Core.Service
|
|||||||
//if (!urlSet.Contains(permission.Replace(":","/")))
|
//if (!urlSet.Contains(permission.Replace(":","/")))
|
||||||
// throw Oops.Oh(ErrorCode.meu1005);
|
// throw Oops.Oh(ErrorCode.meu1005);
|
||||||
}
|
}
|
||||||
//按钮可以设置绑定菜单
|
|
||||||
if(!isVisibleParent && type.Equals((int)MenuType.BTN))
|
// 检查上级菜单的类型是否正确
|
||||||
|
var pid = input.Pid;
|
||||||
|
var flag = true;
|
||||||
|
var empty = System.Guid.Empty.ToString();
|
||||||
|
switch(type)
|
||||||
{
|
{
|
||||||
throw Oops.Oh(ErrorCode.D4004);
|
// 目录必须在顶级下
|
||||||
|
case (int)MenuType.DIR:
|
||||||
|
flag = pid.Equals(empty);
|
||||||
|
break;
|
||||||
|
// 菜单必须在顶级或目录下
|
||||||
|
case (int)MenuType.MENU:
|
||||||
|
if (!pid.Equals(empty))
|
||||||
|
{
|
||||||
|
var parent = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == pid);
|
||||||
|
flag = parent.Type.Equals((int)MenuType.DIR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// 功能必须在菜单下
|
||||||
|
case (int)MenuType.FUNCTION:
|
||||||
|
{
|
||||||
|
var parent = await _sysMenuRep.DetachedEntities.FirstOrDefaultAsync(p => p.Id == pid);
|
||||||
|
flag = parent == null ? false : parent.Type.Equals((int)MenuType.MENU);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag)
|
||||||
|
{
|
||||||
|
throw Oops.Oh("父级菜单类型错误");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +268,7 @@ namespace Ewide.Core.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 校验参数
|
// 校验参数
|
||||||
CheckMenuParam(input);
|
await CheckMenuParam(input);
|
||||||
|
|
||||||
var menu = input.Adapt<SysMenu>();
|
var menu = input.Adapt<SysMenu>();
|
||||||
menu.Pids = await CreateNewPids(input.Pid);
|
menu.Pids = await CreateNewPids(input.Pid);
|
||||||
@@ -296,7 +324,7 @@ namespace Ewide.Core.Service
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 校验参数
|
// 校验参数
|
||||||
CheckMenuParam(input);
|
await CheckMenuParam(input);
|
||||||
// 如果是编辑,父id不能为自己的子节点
|
// 如果是编辑,父id不能为自己的子节点
|
||||||
var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
|
var childIdList = await _sysMenuRep.DetachedEntities.Where(u => u.Pids.Contains(input.Id.ToString()))
|
||||||
.Select(u => u.Id).ToListAsync();
|
.Select(u => u.Id).ToListAsync();
|
||||||
@@ -360,7 +388,7 @@ namespace Ewide.Core.Service
|
|||||||
// 更新当前菜单
|
// 更新当前菜单
|
||||||
oldMenu = input.Adapt<SysMenu>();
|
oldMenu = input.Adapt<SysMenu>();
|
||||||
oldMenu.Pids = newPids;
|
oldMenu.Pids = newPids;
|
||||||
await oldMenu.UpdateAsync(ignoreNullValues: true);
|
await oldMenu.UpdateExcludeAsync(new[] { nameof(SysMenu.Type) }, ignoreNullValues: true);
|
||||||
|
|
||||||
// 清除缓存
|
// 清除缓存
|
||||||
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
await _sysCacheService.DelByPatternAsync(CommonConst.CACHE_KEY_MENU);
|
||||||
|
|||||||
@@ -300,6 +300,14 @@
|
|||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
>iframe {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,23 @@ import { Button, Drawer, message as Message, Modal } from 'antd'
|
|||||||
import { cloneDeep, isEqual } from 'lodash'
|
import { cloneDeep, isEqual } from 'lodash'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染对话框
|
* 渲染对话框
|
||||||
* @param {*} props
|
* @param {*} props
|
||||||
* @param {*} on
|
* @param {*} on
|
||||||
* @param {*} childWithProps
|
* @param {*} childWithProps
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function renderModal(props, on, childWithProps) {
|
function renderModal(props, on, childWithProps) {
|
||||||
|
|
||||||
on = {
|
on = {
|
||||||
...on,
|
...on,
|
||||||
onCancel: () => this.onClose()
|
onCancel: () => this.onClose(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Modal className="yo-modal-form" {...props} {...on}>
|
return (
|
||||||
{childWithProps}
|
<Modal className="yo-modal-form" {...props} {...on}>
|
||||||
</Modal>
|
{childWithProps}
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,27 +32,33 @@ function renderModal(props, on, childWithProps) {
|
|||||||
function renderDrawer(props, on, childWithProps) {
|
function renderDrawer(props, on, childWithProps) {
|
||||||
on = {
|
on = {
|
||||||
...on,
|
...on,
|
||||||
onClose: () => this.onClose()
|
onClose: () => this.onClose(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Drawer className="yo-drawer-form" {...props} {...on}>
|
// react在这里会对该组件不存在的props抛出异常
|
||||||
<div class="yo-drawer-form--body">
|
;['action', 'onSuccess', 'onOk', 'confirmLoading'].forEach(p => {
|
||||||
{childWithProps}
|
delete props[p]
|
||||||
</div>
|
})
|
||||||
<div className="ant-drawer-footer">
|
|
||||||
<Button onClick={on.onClose}>取消</Button>
|
return (
|
||||||
<Button loading={this.state.confirmLoading} onClick={on.onOk} type="primary">确定</Button>
|
<Drawer className="yo-drawer-form" {...props} onClose={() => on.onClose()}>
|
||||||
</div>
|
<div className="yo-drawer-form--body">{childWithProps}</div>
|
||||||
</Drawer>
|
<div className="ant-drawer-footer">
|
||||||
|
<Button onClick={on.onClose}>取消</Button>
|
||||||
|
<Button loading={this.state.confirmLoading} onClick={on.onOk} type="primary">
|
||||||
|
确定
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ModalForm extends Component {
|
export default class ModalForm extends Component {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
// 弹窗显示/隐藏
|
// 弹窗显示/隐藏
|
||||||
visible: false,
|
visible: false,
|
||||||
// 提交状态
|
// 提交状态
|
||||||
confirmLoading: false
|
confirmLoading: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 子元素实例
|
// 子元素实例
|
||||||
@@ -67,12 +73,11 @@ export default class ModalForm extends Component {
|
|||||||
snapshot = null
|
snapshot = null
|
||||||
|
|
||||||
// 完成操作
|
// 完成操作
|
||||||
action = async () => { }
|
action = async () => {}
|
||||||
|
|
||||||
// 是否在关闭时校验数据改变
|
// 是否在关闭时校验数据改变
|
||||||
compareOnClose = true
|
compareOnClose = true
|
||||||
|
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
@@ -143,7 +148,7 @@ export default class ModalForm extends Component {
|
|||||||
content: '当前内容已更改,是否确认不保存并且关闭',
|
content: '当前内容已更改,是否确认不保存并且关闭',
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
this.close()
|
this.close()
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -175,39 +180,33 @@ export default class ModalForm extends Component {
|
|||||||
this.props.onSuccess(postData)
|
this.props.onSuccess(postData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
this.setState({ confirmLoading: false })
|
this.setState({ confirmLoading: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
...this.props,
|
...this.props,
|
||||||
visible: this.state.visible,
|
visible: this.state.visible,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
|
|
||||||
confirmLoading: this.state.confirmLoading
|
confirmLoading: this.state.confirmLoading,
|
||||||
}
|
}
|
||||||
|
|
||||||
const on = {
|
const on = {
|
||||||
onOk: () => this.onOk()
|
onOk: () => this.onOk(),
|
||||||
}
|
}
|
||||||
|
|
||||||
const childWithProps = React.cloneElement(
|
const childWithProps = React.cloneElement(React.Children.only(this.props.children), {
|
||||||
React.Children.only(this.props.children),
|
created: childNode => {
|
||||||
{
|
this.childNode.current = childNode
|
||||||
created: childNode => {
|
this.onCreated()
|
||||||
this.childNode.current = childNode
|
},
|
||||||
this.onCreated()
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return this.type === 'modal' ?
|
return this.type === 'modal'
|
||||||
renderModal.call(this, props, on, childWithProps)
|
? renderModal.call(this, props, on, childWithProps)
|
||||||
:
|
: renderDrawer.call(this, props, on, childWithProps)
|
||||||
renderDrawer.call(this, props, on, childWithProps)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,29 +7,31 @@ import { api } from 'common/api'
|
|||||||
import { EMPTY_ID } from 'util/global'
|
import { EMPTY_ID } from 'util/global'
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
type: '1',
|
type: 1,
|
||||||
openType: '1',
|
openType: 1,
|
||||||
|
weight: '2',
|
||||||
visible: true,
|
visible: true,
|
||||||
sort: 100
|
sort: 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class form extends Component {
|
export default class form extends Component {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
// 加载状态
|
// 加载状态
|
||||||
loading: true,
|
loading: true,
|
||||||
codes: {
|
codes: {
|
||||||
menuType: [],
|
menuType: [],
|
||||||
openType: []
|
openType: [],
|
||||||
|
menuWeight: [],
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
appList: [],
|
appList: [],
|
||||||
parentTreeData: []
|
parentTreeData: [],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addType: [],
|
||||||
type: initialValues.type,
|
type: initialValues.type,
|
||||||
openType: initialValues.openType,
|
openType: initialValues.openType,
|
||||||
icon: ''
|
icon: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单实例
|
// 表单实例
|
||||||
@@ -54,42 +56,46 @@ export default class form extends Component {
|
|||||||
* @param {*} params
|
* @param {*} params
|
||||||
*/
|
*/
|
||||||
async fillData(params) {
|
async fillData(params) {
|
||||||
|
const form = this.form.current
|
||||||
this.record = cloneDeep(params.record)
|
this.record = cloneDeep(params.record)
|
||||||
//#region 从后端转换成前段所需格式
|
//#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()
|
const appList = await this.onLoadSysApplist()
|
||||||
let parentTreeData = []
|
let parentTreeData = []
|
||||||
if (params.isParent) {
|
if (params.isParent) {
|
||||||
parentTreeData = await this.onLoadMenuTree(params.parent.application)
|
parentTreeData = await this.onLoadMenuTree(params.parent.application)
|
||||||
} else if (params.record) {
|
}
|
||||||
|
|
||||||
|
if (params.record) {
|
||||||
parentTreeData = await this.onLoadMenuTree(params.record.application)
|
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
|
const icon = params.record && params.record.icon
|
||||||
this.setState({
|
this.setState({
|
||||||
codes: {
|
codes,
|
||||||
menuType,
|
|
||||||
openType
|
|
||||||
},
|
|
||||||
options: {
|
options: {
|
||||||
appList,
|
appList,
|
||||||
parentTreeData
|
parentTreeData,
|
||||||
},
|
},
|
||||||
icon
|
icon,
|
||||||
})
|
})
|
||||||
//#endregion
|
//#endregion
|
||||||
const form = this.form.current
|
|
||||||
if (params.isParent) {
|
if (params.isParent) {
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
pid: params.parent.id,
|
pid: params.parent.id,
|
||||||
application: params.parent.application
|
application: params.parent.application,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
form.setFieldsValue(this.record)
|
form.setFieldsValue(this.record)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({ loading: false })
|
||||||
loading: false
|
|
||||||
})
|
|
||||||
|
|
||||||
this.onTypeChange()
|
this.onTypeChange()
|
||||||
}
|
}
|
||||||
@@ -123,30 +129,31 @@ export default class form extends Component {
|
|||||||
|
|
||||||
async onLoadMenuTree(application) {
|
async onLoadMenuTree(application) {
|
||||||
const { data } = await api.getMenuTree({ application })
|
const { data } = await api.getMenuTree({ application })
|
||||||
return [{
|
return [
|
||||||
id: EMPTY_ID,
|
{
|
||||||
parentId: undefined,
|
id: EMPTY_ID,
|
||||||
title: '顶级',
|
parentId: undefined,
|
||||||
value: EMPTY_ID,
|
title: '顶级',
|
||||||
pid: undefined,
|
value: EMPTY_ID,
|
||||||
children: data,
|
pid: undefined,
|
||||||
}]
|
children: data,
|
||||||
|
},
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onTypeChange() {
|
onTypeChange() {
|
||||||
this.onTypeChangeGroup()
|
this.onTypeChangeGroup()
|
||||||
const form = this.form.current
|
// const form = this.form.current
|
||||||
const { type } = form.getFieldsValue()
|
// const { type } = form.getFieldsValue()
|
||||||
if (['0', '2'].includes(type)) {
|
// if ([0, 2].includes(type)) {
|
||||||
form.setFieldsValue({
|
// form.setFieldsValue({
|
||||||
openType: '0'
|
// openType: 0,
|
||||||
})
|
// })
|
||||||
} else {
|
// } else {
|
||||||
form.setFieldsValue({
|
// form.setFieldsValue({
|
||||||
openType: '1'
|
// openType: 1,
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenTypeChange() {
|
onOpenTypeChange() {
|
||||||
@@ -168,178 +175,221 @@ export default class form extends Component {
|
|||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
type,
|
type,
|
||||||
openType
|
openType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async onApplicationChange(value) {
|
async onApplicationChange(value) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: true
|
loading: true,
|
||||||
})
|
})
|
||||||
const parentTreeData = await this.onLoadMenuTree(value)
|
const parentTreeData = await this.onLoadMenuTree(value)
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
options: {
|
options: {
|
||||||
...this.state.options,
|
...this.state.options,
|
||||||
parentTreeData
|
parentTreeData,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
this.form.current.setFieldsValue({
|
this.form.current.setFieldsValue({
|
||||||
pid: undefined
|
pid: undefined,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectIcon(icon) {
|
onSelectIcon(icon) {
|
||||||
this.form.current.setFieldsValue({
|
this.form.current.setFieldsValue({
|
||||||
icon
|
icon,
|
||||||
})
|
})
|
||||||
this.setState({ icon })
|
this.setState({ icon })
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { loading, codes, options, addType, type, openType, icon } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form initialValues={initialValues} ref={this.form} className="yo-form">
|
||||||
initialValues={initialValues}
|
<Spin spinning={loading} indicator={<AntIcon type="loading" />}>
|
||||||
ref={this.form}
|
|
||||||
className="yo-form"
|
|
||||||
>
|
|
||||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
|
||||||
<div className="yo-form-group">
|
<div className="yo-form-group">
|
||||||
<h3 className="h3">基本信息</h3>
|
<h3 className="h3">基本信息</h3>
|
||||||
<div className="yo-form-group">
|
<div className="yo-form-group">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="菜单类型"
|
label="菜单类型"
|
||||||
name="type"
|
name="type"
|
||||||
help={
|
tooltip={
|
||||||
<>
|
<>
|
||||||
目录:默认添加在顶级
|
目录:一级菜单,默认添加在顶级
|
||||||
<br />菜单:
|
<br />
|
||||||
<br />按钮:
|
菜单:二级菜单
|
||||||
|
<br />
|
||||||
|
按钮:菜单中对应到接口的功能
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
rules={[{ required: true, message: '请选择菜单类型' }]}
|
rules={[{ required: true, message: '请选择菜单类型' }]}
|
||||||
>
|
>
|
||||||
<Radio.Group onChange={(e) => this.onTypeChange(e)}>
|
<Radio.Group onChange={e => this.onTypeChange(e)}>
|
||||||
{
|
{codes.menuType.map(item => {
|
||||||
this.state.codes.menuType.map(item => {
|
return (
|
||||||
return (
|
<Radio.Button
|
||||||
<Radio.Button
|
key={item.code}
|
||||||
key={item.code}
|
value={+item.code}
|
||||||
value={item.code}
|
disabled={!addType.includes(+item.code)}
|
||||||
>{item.value}</Radio.Button>
|
>
|
||||||
)
|
{item.value}
|
||||||
})
|
</Radio.Button>
|
||||||
}
|
)
|
||||||
|
})}
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="名称" name="name" rules={[{ required: true, message: '请输入名称' }]}>
|
<Form.Item
|
||||||
|
label="名称"
|
||||||
|
name="name"
|
||||||
|
rules={[{ required: true, message: '请输入名称' }]}
|
||||||
|
>
|
||||||
<Input autoComplete="off" placeholder="请输入名称" />
|
<Input autoComplete="off" placeholder="请输入名称" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="唯一编码" name="code">
|
<Form.Item label="唯一编码" name="code">
|
||||||
<Input autoComplete="off" placeholder="请输入唯一编码" />
|
<Input autoComplete="off" placeholder="请输入唯一编码" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="所属应用" name="application" rules={[{ required: true, message: '请选择所属应用' }]}>
|
<Form.Item
|
||||||
<Select placeholder="请选择所属应用" onChange={(value) => this.onApplicationChange(value)}>
|
label="所属应用"
|
||||||
{
|
name="application"
|
||||||
this.state.options.appList.map(item => {
|
rules={[{ required: true, message: '请选择所属应用' }]}
|
||||||
return (
|
>
|
||||||
<Select.Option
|
<Select
|
||||||
key={item.code}
|
placeholder="请选择所属应用"
|
||||||
value={item.code}
|
onChange={value => this.onApplicationChange(value)}
|
||||||
>{item.name}</Select.Option>
|
>
|
||||||
)
|
{options.appList.map(item => {
|
||||||
})
|
return (
|
||||||
}
|
<Select.Option key={item.code} value={item.code}>
|
||||||
|
{item.name}
|
||||||
|
</Select.Option>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{type != 0 && (
|
||||||
this.state.type != 0 &&
|
<Form.Item
|
||||||
<Form.Item label="父级菜单" name="pid" rules={[{ required: true, message: '请选择父级' }]}>
|
label="父级菜单"
|
||||||
|
name="pid"
|
||||||
|
rules={[{ required: true, message: '请选择父级' }]}
|
||||||
|
>
|
||||||
<TreeSelect
|
<TreeSelect
|
||||||
dropdownStyle={{ maxHeight: '300px', overflow: 'auto' }}
|
dropdownStyle={{ maxHeight: '300px', overflow: 'auto' }}
|
||||||
treeData={this.state.options.parentTreeData}
|
treeData={options.parentTreeData}
|
||||||
placeholder="请选择父级菜单"
|
placeholder="请选择父级菜单"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</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>
|
</div>
|
||||||
<h3 className="h3">扩展信息</h3>
|
<h3 className="h3">扩展信息</h3>
|
||||||
<div className="yo-form-group">
|
<div className="yo-form-group">
|
||||||
{
|
{type == 1 && (
|
||||||
this.state.type == 1 &&
|
|
||||||
<Form.Item label="打开方式" name="openType">
|
<Form.Item label="打开方式" name="openType">
|
||||||
<Radio.Group onChange={(e) => this.onOpenTypeChange(e)}>
|
<Radio.Group onChange={e => this.onOpenTypeChange(e)}>
|
||||||
{
|
{codes.openType.map(item => {
|
||||||
this.state.codes.openType.map(item => {
|
return (
|
||||||
return (
|
<Radio.Button key={item.code} value={+item.code}>
|
||||||
<Radio.Button
|
{item.value}
|
||||||
key={item.code}
|
</Radio.Button>
|
||||||
value={item.code}
|
)
|
||||||
>{item.value}</Radio.Button>
|
})}
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
{
|
{type == 1 && openType == 1 && (
|
||||||
this.state.type == 1 && this.state.openType == 1 &&
|
<Form.Item
|
||||||
<Form.Item label="前端组件" name="component" rules={[{ required: true, message: '请输入前端组件' }]}>
|
label="前端组件"
|
||||||
|
name="component"
|
||||||
|
tooltip="打开新页签并渲染前端组件"
|
||||||
|
rules={[{ required: true, message: '请输入前端组件' }]}
|
||||||
|
>
|
||||||
<Input autoComplete="off" placeholder="请输入前端组件" />
|
<Input autoComplete="off" placeholder="请输入前端组件" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
{
|
{type == 1 && openType == 2 && (
|
||||||
this.state.type == 1 && this.state.openType == 2 &&
|
<Form.Item
|
||||||
<Form.Item label="内链地址" name="router" rules={[{ required: true, message: '请输入内链地址' }]}>
|
label="内链地址"
|
||||||
|
name="link"
|
||||||
|
tooltip="打开新页签并使用iframe加载页面"
|
||||||
|
rules={[{ required: true, message: '请输入内链地址' }]}
|
||||||
|
>
|
||||||
<Input autoComplete="off" placeholder="请输入内链地址" />
|
<Input autoComplete="off" placeholder="请输入内链地址" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
{
|
{type == 1 && openType == 3 && (
|
||||||
this.state.type == 1 && this.state.openType == 3 &&
|
<Form.Item
|
||||||
<Form.Item label="外链地址" name="link" rules={[{ required: true, message: '请输入外链地址' }]}>
|
label="外链地址"
|
||||||
|
name="redirect"
|
||||||
|
tooltip="打开新的浏览器窗口"
|
||||||
|
rules={[{ required: true, message: '请输入外链地址' }]}
|
||||||
|
>
|
||||||
<Input autoComplete="off" placeholder="请输入外链地址" />
|
<Input autoComplete="off" placeholder="请输入外链地址" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
{
|
{type == 2 && (
|
||||||
this.state.type == 2 &&
|
<Form.Item
|
||||||
<Form.Item label="权限标识" name="permission" rules={[{ required: true, message: '请输入权限标识' }]}>
|
label="权限标识"
|
||||||
|
name="permission"
|
||||||
|
rules={[{ required: true, message: '请输入权限标识' }]}
|
||||||
|
>
|
||||||
<Input autoComplete="off" placeholder="请输入权限标识" />
|
<Input autoComplete="off" placeholder="请输入权限标识" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
{
|
{type == 2 && (
|
||||||
this.state.type == 2 &&
|
<Form.Item
|
||||||
<Form.Item label="关联上级菜单显示" name="visibleParent" valuePropName="checked">
|
label="关联上级菜单显示"
|
||||||
|
name="visibleParent"
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
<Form.Item label="可见性" name="visible" valuePropName="checked">
|
<Form.Item label="可见性" name="visible" valuePropName="checked">
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{type != 2 && (
|
||||||
this.state.type != 2 &&
|
|
||||||
<Form.Item label="图标" name="icon">
|
<Form.Item label="图标" name="icon">
|
||||||
<Input
|
<Input
|
||||||
disabled
|
disabled
|
||||||
placeholder="请选择图标"
|
placeholder="请选择图标"
|
||||||
addonBefore={
|
addonBefore={icon && <AntIcon type={icon} />}
|
||||||
this.state.icon &&
|
|
||||||
<AntIcon type={this.state.icon} />
|
|
||||||
}
|
|
||||||
addonAfter={
|
addonAfter={
|
||||||
<AntIcon
|
<AntIcon
|
||||||
type="setting"
|
type="setting"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
this
|
this.iconSelector.current.open(
|
||||||
.iconSelector
|
this.form.current.getFieldValue('icon')
|
||||||
.current
|
)
|
||||||
.open(this.form.current.getFieldValue('icon'))
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
}
|
)}
|
||||||
<Form.Item label="排序" name="sort">
|
<Form.Item label="排序" name="sort">
|
||||||
<InputNumber
|
<InputNumber
|
||||||
max={1000}
|
max={1000}
|
||||||
@@ -355,7 +405,7 @@ export default class form extends Component {
|
|||||||
</div>
|
</div>
|
||||||
</Spin>
|
</Spin>
|
||||||
|
|
||||||
<IconSelector ref={this.iconSelector} onSelect={(icon) => this.onSelectIcon(icon)} />
|
<IconSelector ref={this.iconSelector} onSelect={icon => this.onSelectIcon(icon)} />
|
||||||
</Form>
|
</Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { Component } from 'react'
|
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 { isEqual } from 'lodash'
|
||||||
import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions } from 'components'
|
import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions } from 'components'
|
||||||
import { api } from 'common/api'
|
import { api } from 'common/api'
|
||||||
@@ -24,6 +24,7 @@ export default class index extends Component {
|
|||||||
codes: {
|
codes: {
|
||||||
menuType: [],
|
menuType: [],
|
||||||
menuWeight: [],
|
menuWeight: [],
|
||||||
|
openType: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,9 +56,36 @@ export default class index extends Component {
|
|||||||
render: text => text && <AntIcon type={text} />,
|
render: text => text && <AntIcon type={text} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '前端组件',
|
title: '连接',
|
||||||
width: 220,
|
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: '排序',
|
title: '排序',
|
||||||
@@ -83,7 +111,9 @@ export default class index extends Component {
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<QueryTableActions>
|
<QueryTableActions>
|
||||||
<Auth auth="sysMenu:edit">
|
<Auth auth="sysMenu:edit">
|
||||||
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
|
<a onClick={() => this.onOpen({ modal: this.editForm, record })}>
|
||||||
|
编辑
|
||||||
|
</a>
|
||||||
</Auth>
|
</Auth>
|
||||||
<Auth auth="sysMenu:delete">
|
<Auth auth="sysMenu:delete">
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
@@ -96,7 +126,16 @@ export default class index extends Component {
|
|||||||
</Auth>
|
</Auth>
|
||||||
{record.type < 2 && (
|
{record.type < 2 && (
|
||||||
<Auth auth="sysMenu:add">
|
<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 ? '新增子菜单' : '新增功能'}
|
{record.type == 0 ? '新增子菜单' : '新增功能'}
|
||||||
</a>
|
</a>
|
||||||
</Auth>
|
</Auth>
|
||||||
@@ -125,7 +164,7 @@ export default class index extends Component {
|
|||||||
*/
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.table.current.onLoading()
|
this.table.current.onLoading()
|
||||||
getDictData('menu_type', 'menu_weight').then(res => {
|
getDictData('menu_type', 'menu_weight', 'open_type').then(res => {
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
codes: res,
|
codes: res,
|
||||||
@@ -162,7 +201,7 @@ export default class index extends Component {
|
|||||||
name = toCamelCase(name)
|
name = toCamelCase(name)
|
||||||
const codes = this.state.codes[name]
|
const codes = this.state.codes[name]
|
||||||
if (codes) {
|
if (codes) {
|
||||||
const c = codes.find(p => p.code === code)
|
const c = codes.find(p => p.code == code)
|
||||||
if (c) {
|
if (c) {
|
||||||
return c.value
|
return c.value
|
||||||
}
|
}
|
||||||
@@ -175,15 +214,17 @@ export default class index extends Component {
|
|||||||
* @param {*} modal
|
* @param {*} modal
|
||||||
* @param {*} record
|
* @param {*} record
|
||||||
*/
|
*/
|
||||||
onOpen(modal, record, isParent = false) {
|
onOpen({ modal, record, isParent = false, addType = [] }) {
|
||||||
const params = isParent
|
const params = isParent
|
||||||
? {
|
? {
|
||||||
parent: record,
|
parent: record,
|
||||||
isParent,
|
isParent,
|
||||||
|
addType,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
record,
|
record,
|
||||||
isParent,
|
isParent,
|
||||||
|
addType,
|
||||||
}
|
}
|
||||||
|
|
||||||
modal.current.open(params)
|
modal.current.open(params)
|
||||||
@@ -246,7 +287,9 @@ export default class index extends Component {
|
|||||||
<Tooltip title="编辑">
|
<Tooltip title="编辑">
|
||||||
<a
|
<a
|
||||||
className="link-gray"
|
className="link-gray"
|
||||||
onClick={() => this.onOpen(this.editForm, item)}
|
onClick={() =>
|
||||||
|
this.onOpen({ modal: this.editForm, record: item })
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<AntIcon type="edit" />
|
<AntIcon type="edit" />
|
||||||
</a>
|
</a>
|
||||||
@@ -280,9 +323,12 @@ export default class index extends Component {
|
|||||||
if (isFunction) {
|
if (isFunction) {
|
||||||
grids.push(
|
grids.push(
|
||||||
<Card.Grid
|
<Card.Grid
|
||||||
|
key={0}
|
||||||
style={{ padding: '18px 12px', cursor: 'pointer' }}
|
style={{ padding: '18px 12px', cursor: 'pointer' }}
|
||||||
className="text-center"
|
className="text-center"
|
||||||
onClick={() => this.onOpen(this.addForm, record, true)}
|
onClick={() =>
|
||||||
|
this.onOpen({ modal: this.addForm, record, isParent: true, addType: [2] })
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<AntIcon type="plus" className="text-normal h2" />
|
<AntIcon type="plus" className="text-normal h2" />
|
||||||
@@ -331,9 +377,11 @@ export default class index extends Component {
|
|||||||
<Auth auth="sysMenu:add">
|
<Auth auth="sysMenu:add">
|
||||||
<Button
|
<Button
|
||||||
icon={<AntIcon type="plus" />}
|
icon={<AntIcon type="plus" />}
|
||||||
onClick={() => this.onOpen(this.addForm)}
|
onClick={() =>
|
||||||
|
this.onOpen({ modal: this.addForm, addType: [0, 1] })
|
||||||
|
}
|
||||||
>
|
>
|
||||||
新增{name}
|
新增目录/菜单
|
||||||
</Button>
|
</Button>
|
||||||
</Auth>
|
</Auth>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class ComponentDynamic extends Component {
|
|||||||
if (this.props.onRef) {
|
if (this.props.onRef) {
|
||||||
this.props.onRef(this)
|
this.props.onRef(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +72,40 @@ class ComponentDynamic extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Iframe extends Component {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
if (this.props.onRef) {
|
||||||
|
this.props.onRef(this)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.onRef) {
|
||||||
|
this.props.onRef(this)
|
||||||
|
}
|
||||||
|
this.loadComponent()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadComponent() {
|
||||||
|
NProgress.start()
|
||||||
|
const iframe = this.refs.content
|
||||||
|
iframe.onload = () => {
|
||||||
|
NProgress.done()
|
||||||
|
}
|
||||||
|
iframe.onerror = () => {
|
||||||
|
NProgress.done()
|
||||||
|
}
|
||||||
|
iframe.src = this.props.src
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { title } = this.props
|
||||||
|
|
||||||
|
return <iframe ref="content" title={title} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default class index extends Component {
|
export default class index extends Component {
|
||||||
state = {
|
state = {
|
||||||
actived: '',
|
actived: '',
|
||||||
@@ -191,14 +224,23 @@ export default class index extends Component {
|
|||||||
' yo-tab-external-tabpane'
|
' yo-tab-external-tabpane'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ComponentDynamic
|
{pane.openType === 1 ? (
|
||||||
path={pane.path}
|
<ComponentDynamic
|
||||||
id={pane.key}
|
path={pane.path}
|
||||||
key={pane.key}
|
id={pane.key}
|
||||||
param={pane.param}
|
key={pane.key}
|
||||||
paneActived={pane.key === actived}
|
param={pane.param}
|
||||||
onRef={p => this.panes.push(p)}
|
paneActived={pane.key === actived}
|
||||||
/>
|
onRef={p => this.panes.push(p)}
|
||||||
|
/>
|
||||||
|
) : pane.openType === 2 ? (
|
||||||
|
<Iframe
|
||||||
|
src={pane.path}
|
||||||
|
title={pane.key}
|
||||||
|
id={pane.key}
|
||||||
|
onRef={p => this.panes.push(p)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export default class search extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSelect(value, option) {
|
onSelect(value, option) {
|
||||||
const { id, meta, component } = option.menu
|
const { id, meta, component, link, redirect, openType } = option.menu
|
||||||
|
|
||||||
// 选中时清空输入框内容,并失去焦点
|
// 选中时清空输入框内容,并失去焦点
|
||||||
this.setState({ searchValue: '' })
|
this.setState({ searchValue: '' })
|
||||||
@@ -88,7 +88,19 @@ export default class search extends Component {
|
|||||||
key: id,
|
key: id,
|
||||||
title: meta.title,
|
title: meta.title,
|
||||||
icon: meta.icon,
|
icon: meta.icon,
|
||||||
path: component,
|
path: (() => {
|
||||||
|
switch (openType) {
|
||||||
|
case 1:
|
||||||
|
return component
|
||||||
|
case 2:
|
||||||
|
return link
|
||||||
|
case 3:
|
||||||
|
return redirect
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
openType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,11 +50,25 @@ export default class index extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onOpenContentWindow = menu => {
|
onOpenContentWindow = menu => {
|
||||||
|
const { id, meta, component, link, redirect, openType } = menu
|
||||||
|
|
||||||
window.openContentWindow({
|
window.openContentWindow({
|
||||||
key: menu.id,
|
key: id,
|
||||||
title: menu.meta.title,
|
title: meta.title,
|
||||||
icon: menu.meta.icon,
|
icon: meta.icon,
|
||||||
path: menu.component,
|
path: (() => {
|
||||||
|
switch (openType) {
|
||||||
|
case 1:
|
||||||
|
return component
|
||||||
|
case 2:
|
||||||
|
return link
|
||||||
|
case 3:
|
||||||
|
return redirect
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
openType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,31 @@ export default class index extends Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = settings.path.startsWith('/') ? settings.path : `/${settings.path}`
|
let path = (p => {
|
||||||
|
if (p.startsWith('http')) return p
|
||||||
|
if (p.startsWith('/')) return p
|
||||||
|
else return `/${p}`
|
||||||
|
})(settings.path)
|
||||||
|
|
||||||
|
if ([2, 3].includes(settings.openType)) {
|
||||||
|
const param = (p => {
|
||||||
|
const arr = []
|
||||||
|
if (p && p.constructor === Object) {
|
||||||
|
Object.keys(p).forEach(key => {
|
||||||
|
arr.push(`${key}=${(p[key] || '').toString()}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return arr.join('&')
|
||||||
|
})(settings.param)
|
||||||
|
|
||||||
|
path += param ? `?${param}` : ''
|
||||||
|
|
||||||
|
if (settings.openType === 3) {
|
||||||
|
// 打开新的浏览器窗口
|
||||||
|
window.open(path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向标签页队列中添加一个新的标签页
|
* 向标签页队列中添加一个新的标签页
|
||||||
@@ -120,7 +144,9 @@ export default class index extends Component {
|
|||||||
path,
|
path,
|
||||||
param: settings.param,
|
param: settings.param,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
|
openType: settings.openType || 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
panes: [...this.state.panes, newPane],
|
panes: [...this.state.panes, newPane],
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user