通用权限管理系统之权限菜单zTree树的展示及移动的处理方法
在通用权限管理系统中,有很多数据结构是有父子关系的,如组织机构,部门,权限菜单等,在展示的时候,大多数是通过zTree树的形式展现的,如下:
权限菜单展示
这种数据后台输出比较容易处理,参考如下获取某个子系统的全部操作菜单:
后台输出zTree树的数据
/// <summary>
/// 获取module树结构数据
/// </summary>
/// <param name="systemCode"></param>
/// <returns></returns>
public ActionResult GetModuleTree(string systemCode = null)
{
if (string.IsNullOrWhiteSpace(systemCode))
{
systemCode = BaseSystemInfo.SystemCode;
}
string tableName = systemCode + "Module"; ;
BaseModuleManager moduleManager = new BaseModuleManager(UserInfo, tableName);
List<KeyValuePair<string, object>> parameters = new List<KeyValuePair<string, object>>();
parameters.Add(new KeyValuePair<string, object>(BaseModuleEntity.FieldEnabled, ));
//parameters.Add(new KeyValuePair<string, object>(BaseModuleEntity.FieldDeletionStateCode, 0));
parameters.Add(new KeyValuePair<string, object>(BaseModuleEntity.FieldIsVisible, ));
var entityList = moduleManager.GetList<BaseModuleEntity>(parameters, BaseModuleEntity.FieldSortCode); Hashtable hashTable = new Hashtable();
if (entityList != null)
{
var result = (from p in entityList select new { id = p.Id, parentId = p.ParentId, name = p.FullName }).ToList();
hashTable.Add("treeNodes", result);
}
else
{
hashTable.Add("treeNodes", null);
}
return Json(hashTable, JsonRequestBehavior.AllowGet);
}
前端的JS部分的代码
var _zTree;
//获取树对象
function getTree() {
return $.fn.zTree.getZTreeObj("tree-1");
} //刷新树
function RefreshTree() {
var systemCode = $("#systemCode").attr("relValue");
if (typeof (systemCode) != "undefined") {
setting1.async.url = "/Module/GetModuleTree?systemCode=" + systemCode;
$.fn.zTree.init($("#tree-1"), setting1);
_zTree = $.fn.zTree.getZTreeObj("tree-1");
}
} //过滤
function filter(treeNodes) {
var filterName = $("#OrganizeName").attr("reltext");
if (filterName == "AAAA" || filterName == "") {
return false;
}
return (treeNodes.name.indexOf(filterName) > -1);
} //树的设置
var setting1 = {
async: {
enable: true,
dataType: 'JSON',
//返回的JSON数据的名字
dataName: 'treeNodes',
url: "/Module/GetModuleTree",
autoParam: ["id", "name", "desc"],
otherParam: {
"otherParam1": "zTreeAsyncTest1",
"otherParam2": "zTreeAsyncTest2"
}
//,传回的数据格式不是ztree所需要的格式的时候,可以对数据进行转化。正常情况下不需要实现dataFilter
//dataFilter: filter
},
view: {
addHoverDom: addHoverDom,
removeHoverDom: removeHoverDom,
selectedMulti: true
},
edit: {
enable: true,
showRemoveBtn: false,
showRenameBtn: false,
renameTitle: "修改",
removeTitle: "删除",
drag: {
isCopy: false,
isMove: true
}
},
callback: {
onClick: onClick,
beforeDrop: function(treeId, treeNodes, targetNode, moveType) { return onDrop(treeId, treeNodes, targetNode, moveType); },
onAsyncSuccess: onAsyncSuccess
}
}; //转移
function onDrop(treeId, treeNodes, targetNode, moveType) {
debugger;
// 当前节点不能移动到当前节点上
var node, newParent = targetNode;
var nodeNames = "",nodeIds="";
for (var i = 0; i < treeNodes.length; i++) {
node = treeNodes[i];
nodeNames += node.name + ",";
nodeIds += node.id + ",";
if (node.id == newParent.id) {
top.Dialog.alert("不能将自己设为自己的父级节点");
return false;
};
}
if (nodeIds.length>0) {
nodeIds = nodeIds.substring(0, nodeIds.length - 1);
}
// 当前节点不能移动到自己的子节点上去
for (var i = 0; i < treeNodes.length; i++) {
//debugger;
// 交换测试
//newParent = treeNodes[0];
//node = targetNode;
node = treeNodes[i];
var pid = newParent.getParentNode();
while (pid != null) {
pid = pid.getParentNode();
if (node == pid) {
top.Dialog.alert("当前节点不能移动到自己的子节点上去");
return false;
}
}
} if (!confirm("你确定要将{0}转移到{1}名下吗?".replace("{0}", '\'' + nodeNames + '\'').replace("{1}", '\'' + newParent.name + '\''))) {
return false;
} else {
var systemCode = $("#systemCode").attr("relValue");
$.ajax({
url: '/Module/MoveTo',
type: 'POST',
data: { moduleIds: nodeIds, parentId: newParent.id, systemCode: systemCode },
success: function(response, options) {
// 重载树
top.Dialog.alert(response.StatusMessage, function() {
RefreshTree();
}
);
}
});
return true;
}
}; //异步加载成功后
function onAsyncSuccess(event, treeId, treeNode, msg) {
_zTree.expandNode(_zTree.getNodes()[0], true, false, false);
} //初始化函数
function initComplete() {
$("#layout1").layout({
leftWidth: 200,
onEndResize: function() {
//g.resetWidth();
}
});
RefreshTree();
//绑定change事件
$("#systemCode").bind("change", function() {
if (!$(this).attr("relValue")) {
top.Dialog.alert("没有选择节点");
} else {
//top.Dialog.alert("选中节点文本:" + $(this).attr("relText") + "<br/>选中节点值:" + $(this).attr("relValue"));
setting1.async.url = "/Module/GetModuleTree?systemCode=" + $(this).attr("relValue"),
$.fn.zTree.init($("#tree-1"), setting1);
_zTree = $.fn.zTree.getZTreeObj("tree-1");
AddModule();
}
});
} //点击树节点
function onClick(event, treeId, treeNode, clickFlag) {
//设置表单的值
$("#frmContent").attr("src", "/Module/Edit?id=" + treeNode.id + "&systemCode=" + $("#systemCode").attr("relValue"));
} var _treeNode; // 添加
function addHoverDom(treeId, treeNode) {
if (treeNode.editNameFlag || $("#addBtn_" + treeNode.id).length > 0) return;
var sObj = $("#" + treeNode.tId + "_span");
var addStr = "<span class='zbutton add' id='addBtn_" + treeNode.id + "' title='添加' onfocus='this.blur();'></span>";
sObj.append(addStr);
var btn = $("#addBtn_" + treeNode.id);
if (btn) {
btn.bind("click", function() {
_treeNode = treeNode;
$("#frmContent").attr("src", "/Module/Add?id=" + treeNode.id + "&systemCode=" + $("#systemCode").attr("relValue"));
return false;
});
}
}; function refreshFrmContent() {
window.frames["frmContent"].location.reload();
}; function removeHoverDom(treeId, treeNode) {
$("#addBtn_" + treeNode.id).unbind().remove();
}; //新增
function AddModule() {
var systemCode = $("#systemCode").attr("relValue");
if (typeof (systemCode) != "undefined") {
$("#frmContent").attr("src", "/Module/Add?systemCode=" + systemCode);
} else {
top.Dialog.alert("请选择一个子系统。");
}
}; // 权限设置
function permissionSet() {
top.Dialog.open({
ID: "selectWin",
URL: "/Module/Permission?systemCode=@ViewBag.SystemCode&moduleId=@moduleEntity.Id", //+ systemCode,
Title: "权限设置",
Width: 640,
Height: 480
});
};
权限菜单的移动
菜单移动的本质是改变菜单的父节点,在编辑时可以通过修改菜单的父节点来实现菜单的移动,为了操作快捷,大多数情况下希望能通过拖动节点来实现菜单的移动,实现的截图如下:
单个菜单的移动,鼠标左键按住需要移动的菜单,拖动到要移动的目的位置,然后松开鼠标左键,此时会弹出确认提示,点击确定,将会执行移动程序处理,点击取消将恢复到原始位置。
点击确定后,菜单移到的位置:
菜单移动支持多个菜单同时移动某个目标位置,
如上图,多个菜单同时移动时,按住Ctrl键,逐个点击要移动的菜单,然后松开Ctrl,鼠标拖动菜单移到目标位置。接下来操作如上。
后台处理菜单的移动方法,包括检查节点能否移动(不能将自己设为自己的父级节点,当前节点不能移动到自己的子节点上去):
/// <summary>
/// 节点移动
/// </summary>
/// <param name="moduleIds"></param>
/// <param name="parentId"></param>
/// <param name="systemCode"></param>
/// <returns></returns>
public ActionResult MoveTo(string moduleIds, string parentId, string systemCode = null)
{
string[] ids = moduleIds.Split(','); if (string.IsNullOrWhiteSpace(systemCode))
{
systemCode = BaseSystemInfo.SystemCode;
}
BaseResult baseResult = new BaseResult();
string message = string.Empty;
if (!MoveCheck(ids, parentId, systemCode, out message))
{
baseResult.Status = false;
baseResult.StatusMessage = message;
}
else
{
string tableName = systemCode + "Module";
var manager = new BaseModuleManager(UserCenterDbHelper, OperateContext.Current.UserInfo, tableName);
// 设置moduleId的父级节点为parentId
int result = 0;
for (int i = 0; i < ids.Length; i++)
{
if (!string.IsNullOrWhiteSpace(ids[i]))
{
result += manager.SetProperty(ids[i], new KeyValuePair<string, object>(BaseModuleEntity.FieldParentId, parentId));
}
}
if (result > 0)
{
baseResult.Status = true;
baseResult.StatusMessage = "移动成功。";
}
else
{
baseResult.Status = false;
baseResult.StatusMessage = "移动失败。";
}
}
return Json(baseResult, JsonRequestBehavior.AllowGet);
} /// <summary>
/// 节点移动检查
/// </summary>
/// <param name="ids"></param>
/// <param name="parentId"></param>
/// <param name="systemCode"></param>
/// <param name="message"></param>
/// <returns></returns>
private bool MoveCheck(string[] ids, string parentId, string systemCode, out string message)
{
message = string.Empty;
// 不能将自己设为自己的父级节点
for (int i = 0; i < ids.Length; i++)
{
if (string.Equals(ids[i], parentId, StringComparison.OrdinalIgnoreCase))
{
message = "不能将自己设为自己的父级节点。";
return false;
}
}
string tableName = systemCode + "Module";
var manager = new BaseModuleManager(UserCenterDbHelper, OperateContext.Current.UserInfo, tableName);
// 目标节点
BaseModuleEntity moduleEntity = manager.GetObject(parentId); // 当前节点不能移动到自己的子节点上去
for (int i = 0; i < ids.Length; i++)
{
while (!string.IsNullOrWhiteSpace(moduleEntity.ParentId))
{
moduleEntity = manager.GetObject(moduleEntity.ParentId);
if (string.Equals(ids[i], moduleEntity.Id, StringComparison.OrdinalIgnoreCase))
{
message = "当前节点不能移动到自己的子节点上去。";
return false;
}
}
} return true;
}
类似的,其它父子类的数据参照这个就可以很方便的处理展示和移动了。
通用权限管理系统之权限菜单zTree树的展示及移动的处理方法的更多相关文章
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(20)-权限管理系统-根据权限获取菜单
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(20)-权限管理系统-根据权限获取菜单 不知不觉到20讲,真是漫长的日子,可惜最近工作挺忙,要不可以有更多 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(20)-权限管理系统-根据权限获取菜单
系列目录 不知不觉到20讲,真是漫长的日子,可惜最近工作挺忙,要不可以有更多的时间来更新,多谢大家的一路支持.如果你觉得好,记得帮我点击推荐^-^ 我们在之前已经插入一些真实数据,其中包含了一个用户和 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(24)-权限管理系统-将权限授权给角色
系列目录 过了个年回来,回顾一下,我们上次讲了角色管理,我们这一次来讲将权限授权给角色,这一节也是大家比较关心的.因为我们已经跑通了整个系统,知道权限的流转,我们先来看一张图 这张图主要分要3块,角色 ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第十节--AdminLTE模板菜单处理
上节我们把布局页,也有的临时的菜单,但是菜单不是应该动态加载的么?,所以我们这节来写菜单.首先我们看一下AdminLTE源码里面的菜单以及结构. <aside class="main- ...
- springboot学习笔记:11.springboot+shiro+mysql+mybatis(通用mapper)+freemarker+ztree+layui实现通用的java后台管理系统(权限管理+用户管理+菜单管理)
一.前言 经过前10篇文章,我们已经可以快速搭建一个springboot的web项目: 今天,我们在上一节基础上继续集成shiro框架,实现一个可以通用的后台管理系统:包括用户管理,角色管理,菜单管理 ...
- 通用权限管理系统数据字典 V3.9 版本,欢迎开发个各种业务系统的朋友们,参考表结构
C#.NET通用权限管理系统组件数据字典 导 航 ◇ (01) BaseItemDetails ◇ (02) BaseItems ◇ (03) BaseLog ◇ (04) BaseMessage ...
- ASP.NET MVC通用权限管理系统(响应布局)源码更新介绍
一.asp.net mvc 通用权限管理系统(响应布局)源码主要以下特点: AngelRM(Asp.net MVC)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash ...
- winform快速开发平台 -> 通用权限管理之动态菜单
这几个月一直忙APP的项目,没来得及更新项目,想想该抽出时间整理一下开发思路,跟大家分享,同时也希望得到宝贵的建议. 先说一下我们的权限管理的的设计思路,首先一个企业信息化管理系统一定会用到权限管理, ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第九节--AdminLTE引入及模板页和布局和菜单
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 AdminLTE AdminLTE 官网地址:https://adminlte.io/themes/AdminLT ...
随机推荐
- HTML中块元素与内联元素的概念
HTML中块元素与内联元素的概念 div就是一个块元素,所谓的块元素就是会独占一行的的元素,无论他的内容有多少,他都会独占一整行. p h1 h2 h3 ... div这个标签没有任何语义,就是一个纯 ...
- HTML文档命名规则
HTML文档是展示Web前段开发工程师成果的最好表示方式,为了便于文档规范化管理,在编写HTML文档时,必须遵循HTML文件命名规则. HTML文档命名规则如下: (1)文档的扩展名为htm或者htm ...
- 第十三课 CSS外观及样式的应用 css学习3
一.1.color: 文本颜色 预定义文本颜色值,如red,blue等 十六进制的颜色值 #fff白色 建议常用的表示方法 RGB代码,如红色可以表示为rgb(255,0,0)或rgb(100%,%0 ...
- C# winform 拖拽效果
//是否在拖拽 bool isDrag = false; //鼠标相对于button控件左上角的坐标 Point contextbtnPoint = Point.Empty; private void ...
- 基于Html5 Plus + Vue + Mui 移动App 开发(二)
基于Html5 Plus + Vue + Mui 移动App 开发(二) 界面效果: 本页面采用Html5 Plus + Vue + Mui 开发移动界面,本页面实现: 1.下拉刷新.上拉获取更多功能 ...
- MATLAB 音响系统工具箱
音响系统工具箱 设计和测试音频处理系统 发行说明 pdf文档 音频系统工具箱™为音频处理系统的设计,仿真和桌面原型设计提供了算法和工具.它支持低延迟信号流式传输到音频接口,交互式参数调整以及数字音频工 ...
- 【Linux】【MySQL】CentOS7安装最新版MySQL8.0.13(最新版MySQL从安装到运行)
1.前言 框框博客在线报时:2018-11-07 19:31:06 当前MySQL最新版本:8.0.13 (听说比5.7快2倍) 官方之前表示:MySQL 8.0 正式版 8.0.11 已发布,MyS ...
- spring笔记----看书笔记
上周末看了一章以前javaee轻量级的书spring部分,简单做了一些笔记 // ApplicationContext ac=new ClassPathXmlApplicationContext(&q ...
- sql 按年月日统计
1.每年select year(ordertime) 年,sum(Total) 销售合计from 订单表group by year(ordertime) 2.每月select year(orderti ...
- Java 8 Stream介绍及使用1
(原) stream的内容比较多,先简单看一下它的说明: A sequence of elements supporting sequential and parallel aggregate * o ...