大家写前端写代码时听的歌是自己先画个草图再做还是怎么着

ztree使用系列四(ztree实现同级拖拽排序并将排序结果保存数据库)
时间: 13:21:29
&&&& 阅读:123
&&&& 评论:
&&&& 收藏:0
& & & &ztree这个系列的最后一篇,也是ztree功能强大的体现之中的一个——排序功能。ztree能够实现全部节点之间任意的拖拽排序功能。我这里依据须要实现了仅仅同意同级之间任意拖拽排序,事实上原理都一样,仅仅是范围缩小了一些,多了一些推断而已。以下是每一层的代码。还是採取仅仅贴出功能代码。由于这个拖拽排序功能我感觉非常不错,所以单独拿出一篇博客来展示,也方便理解。
Jsp页面实现功能的js代码例如以下:
//拖拽前运行
var dragId;
function beforeDrag(treeId, treeNodes) {
for (var i=0,l=treeNodes. i&l; i++) {
dragId = treeNodes[i].pId;
if (treeNodes[i].drag === false) {
//拖拽释放之后运行
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
if(targetNode.pId == dragId){
var data = {id:treeNodes[0].id,targetId:targetNode.id,moveType:moveType};
var confirmVal =
async: false,
type: &post&,
data:data,
url:&&%=request.getContextPath() %&/library/updateLibrarySort/ &,
success: function(json){
if(json==&success& ){
confirmVal =
alert('操作成功!');
alert('亲,操作失败');
error: function(){
alert('亲,网络有点不给力呀。');
return confirmV
alert('亲,仅仅能进行同级排序!');
Controller层代码例如以下:
* 更新分类排序
@RequestMapping(value=&updateLibrarySort/&)
@ResponseBody
public String updateLibrarySort(HttpServletRequest request, HttpServletResponse response,LibraryVo libraryVo) {
String createname=(String) request.getSession().getAttribute(Constants.CURRENT_USER_NAME);
return libraryService.updateLibrarySort(libraryVo,createname);
service层代码例如以下:
* 更新排序
public String updateLibrarySort(LibraryVo libraryVo,String userName){
int numFlag = 0;
Library libraryT = libraryMapper.selectByPrimaryKey(libraryVo.getTargetId());//目标分类信息
Library library = libraryMapper.selectByPrimaryKey(libraryVo.getId());//拖动分类信息
library.setTarget_order_id(libraryT.getOrder_id());
library.setUpdate_time(new Date());//设置时间
library.setUpdate_user(userName);//设置操作人
libraryT.setUpdate_time(new Date());//设置时间
libraryT.setUpdate_user(userName);//设置操作人
Map&String,Object& libraryMap = new
HashMap&String, Object&();//參数集合
if (libraryVo.getMoveType().equals(&prev&)) {//向前移动
libraryMap.put(&pid&, library.getPid());
libraryMap.put(&order_id&, library.getTarget_order_id());
libraryMap.put(&target_order_id&, library.getOrder_id());
List&Library& listLibraryFlag = libraryMapper.findLibraryListByOrderId(libraryMap);
int order_id = libraryT.getOrder_id() + 1;
library.setOrder_id(libraryT.getOrder_id());
libraryT.setOrder_id(order_id);
for (int i = 0; i & listLibraryFlag.size(); i++) {//更新全部受影响的排序字段
Library ly = listLibraryFlag.get(i);
if(!(ly.getId()).equals(library.getId()) && !(ly.getId()).equals(libraryT.getId())){
ly.setUpdate_time(new Date());
ly.setUpdate_user(userName);
ly.setOrder_id(ly.getOrder_id()+1);
libraryMapper.updateOrderId(ly);//更新其它受影响的分类信息
libraryMapper.updateOrderId(library);//更新拖动分类信息
numFlag = libraryMapper.updateOrderId(libraryT);//更新目标分类信息
}else if(libraryVo.getMoveType().equals(&next&)){//向后移动
libraryMap.put(&pid&, library.getPid());
libraryMap.put(&order_id&, library.getOrder_id());
libraryMap.put(&target_order_id&, library.getTarget_order_id());
List&Library& listLibraryFlag = libraryMapper.findLibraryListByOrderId(libraryMap);
int order_id = libraryT.getOrder_id();
library.setOrder_id(order_id);
libraryT.setOrder_id(order_id - 1);
for (int i = 0; i & listLibraryFlag.size(); i++) {//更新全部受影响的排序字段
Library ly = listLibraryFlag.get(i);
if(!(ly.getId()).equals(library.getId()) && !(ly.getId()).equals(libraryT.getId())){
ly.setUpdate_time(new Date());
ly.setUpdate_user(userName);
ly.setOrder_id(ly.getOrder_id() - 1);
libraryMapper.updateOrderId(ly);//更新其它受影响的分类信息
libraryMapper.updateOrderId(library);//更新拖动分类信息
numFlag = libraryMapper.updateOrderId(libraryT);//更新目标分类信息
return ServiceUtil.ReturnString(numFlag);
Mapper层代码例如以下
* 依据pid、order_id和target_order_id查询全部受影响的信息
* @param pid
* @param order_id
* @param target_order_id
public List&Library& findLibraryListByOrderId(Map&String,Object& library);
* @param library
public int updateOrderId(Library library);相应的xml代码例如以下:
& sql id= &Base_Column_List& &
id, pid , name, create_time, update_time, is_delete, update_user, create_user, level_id,
&!-- 更新order_id --&
& update id= &updateOrderId& parameterType=&Library& &
update onair_vms_library
update_time = #{update_time},
update_user = #{update_user},
order_id = #{order_id}
where id = #{id}
&/ update&
&!-- 依据 pid、order_id和target_order_id查询全部受影响的信息 --&
& select id= &findLibraryListByOrderId& resultMap= &BaseResultMap& parameterType =&java.util.Map& &
&include refid =&Base_Column_List&/&
from onair_vms_library
order_id between
#{order_id} and
#{target_order_id}
pid = #{ pid}
&/ select&
& & & &写的一般,不正确的地方欢迎指正,有高效或者更加简便的办法希望可以共享一下,尤其是在排序功能运行保存的时候假设可以不使用循环一条sql能搞定就更加强大了。欢迎大家指点。
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码![原]ztree使用系列四(ztree实现同级拖拽排序并将排序结果保存数据库) - 推酷
[原]ztree使用系列四(ztree实现同级拖拽排序并将排序结果保存数据库)
& & & &ztree这个系列的最后一篇,也是ztree功能强大的体现之一——排序功能。ztree可以实现所有节点之间随意的拖拽排序功能,我这里根据需要实现了只允许同级之间随意拖拽排序,其实原理都一样,只是范围缩小了一些,多了一些判断而已。下面是每一层的代码,还是采取只贴出功能代码,因为这个拖拽排序功能我感觉很不错,所以单独拿出一篇博客来展示,也方便理解。
Jsp页面实现功能的js代码如下:
//拖拽前执行
var dragId;
function beforeDrag(treeId, treeNodes) {
for (var i=0,l=treeNodes. i&l; i++) {
dragId = treeNodes[i].pId;
if (treeNodes[i].drag === false) {
//拖拽释放之后执行
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
if(targetNode.pId == dragId){
var data = {id:treeNodes[0].id,targetId:targetNode.id,moveType:moveType};
var confirmVal =
async: false,
type: &post&,
data:data,
url:&&%=request.getContextPath() %&/library/updateLibrarySort/ &,
success: function(json){
if(json==&success& ){
confirmVal =
alert('操作成功!');
alert('亲,操作失败');
error: function(){
alert('亲,网络有点不给力呀!');
return confirmV
alert('亲,只能进行同级排序!');
Controller层代码如下:
* 更新分类排序
@RequestMapping(value=&updateLibrarySort/&)
@ResponseBody
public String updateLibrarySort(HttpServletRequest request, HttpServletResponse response,LibraryVo libraryVo) {
String createname=(String) request.getSession().getAttribute(Constants.CURRENT_USER_NAME);
return libraryService.updateLibrarySort(libraryVo,createname);
service层代码如下:
* 更新排序
public String updateLibrarySort(LibraryVo libraryVo,String userName){
int numFlag = 0;
Library libraryT = libraryMapper.selectByPrimaryKey(libraryVo.getTargetId());//目标分类信息
Library library = libraryMapper.selectByPrimaryKey(libraryVo.getId());//拖动分类信息
library.setTarget_order_id(libraryT.getOrder_id());
library.setUpdate_time(new Date());//设置时间
library.setUpdate_user(userName);//设置操作人
libraryT.setUpdate_time(new Date());//设置时间
libraryT.setUpdate_user(userName);//设置操作人
Map&String,Object& libraryMap = new
HashMap&String, Object&();//参数集合
if (libraryVo.getMoveType().equals(&prev&)) {//向前移动
libraryMap.put(&pid&, library.getPid());
libraryMap.put(&order_id&, library.getTarget_order_id());
libraryMap.put(&target_order_id&, library.getOrder_id());
List&Library& listLibraryFlag = libraryMapper.findLibraryListByOrderId(libraryMap);
int order_id = libraryT.getOrder_id() + 1;
library.setOrder_id(libraryT.getOrder_id());
libraryT.setOrder_id(order_id);
for (int i = 0; i & listLibraryFlag.size(); i++) {//更新所有受影响的排序字段
Library ly = listLibraryFlag.get(i);
if(!(ly.getId()).equals(library.getId()) && !(ly.getId()).equals(libraryT.getId())){
ly.setUpdate_time(new Date());
ly.setUpdate_user(userName);
ly.setOrder_id(ly.getOrder_id()+1);
libraryMapper.updateOrderId(ly);//更新其他受影响的分类信息
libraryMapper.updateOrderId(library);//更新拖动分类信息
numFlag = libraryMapper.updateOrderId(libraryT);//更新目标分类信息
}else if(libraryVo.getMoveType().equals(&next&)){//向后移动
libraryMap.put(&pid&, library.getPid());
libraryMap.put(&order_id&, library.getOrder_id());
libraryMap.put(&target_order_id&, library.getTarget_order_id());
List&Library& listLibraryFlag = libraryMapper.findLibraryListByOrderId(libraryMap);
int order_id = libraryT.getOrder_id();
library.setOrder_id(order_id);
libraryT.setOrder_id(order_id - 1);
for (int i = 0; i & listLibraryFlag.size(); i++) {//更新所有受影响的排序字段
Library ly = listLibraryFlag.get(i);
if(!(ly.getId()).equals(library.getId()) && !(ly.getId()).equals(libraryT.getId())){
ly.setUpdate_time(new Date());
ly.setUpdate_user(userName);
ly.setOrder_id(ly.getOrder_id() - 1);
libraryMapper.updateOrderId(ly);//更新其他受影响的分类信息
libraryMapper.updateOrderId(library);//更新拖动分类信息
numFlag = libraryMapper.updateOrderId(libraryT);//更新目标分类信息
return ServiceUtil.ReturnString(numFlag);
Mapper层代码如下
* 根据pid、order_id和target_order_id查询所有受影响的信息
* @param pid
* @param order_id
* @param target_order_id
public List&Library& findLibraryListByOrderId(Map&String,Object& library);
* @param library
public int updateOrderId(Library library);
对应的xml代码如下:
& sql id= &Base_Column_List& &
id, pid , name, create_time, update_time, is_delete, update_user, create_user, level_id,
&!-- 更新order_id --&
& update id= &updateOrderId& parameterType=&com.cdvcloud.vms.domain.Library& &
update onair_vms_library
update_time = #{update_time},
update_user = #{update_user},
order_id = #{order_id}
where id = #{id}
&/ update&
&!-- 根据 pid、order_id和target_order_id查询所有受影响的信息 --&
& select id= &findLibraryListByOrderId& resultMap= &BaseResultMap& parameterType =&java.util.Map& &
&include refid =&Base_Column_List&/&
from onair_vms_library
order_id between
#{order_id} and
#{target_order_id}
pid = #{ pid}
&/ select&
& & & &写的一般,不对的地方欢迎指正,有高效或者更加简便的办法希望能够共享一下,尤其是在排序功能执行保存的时候如果能够不使用循环一条sql能搞定就更加强大了,欢迎大家指点。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致ztree 我想关闭它节点之间的拖拽,我不需要该功能,怎么改
最简单的方法:beforeDrag:function(){} 这样你还能继续使用编辑功能。 其实 简单增删改查的Demo 就是这么实现的
--- 共有 1 条评论 ---
是的,其他功能:增删改,我需要使用的,谢谢
setting 的
editable 属性& & & & &之前写了一篇关于 文件夹与文件的操作的文章 &&
把常用的对于文件与文件夹的操作总结了一下,在文章的回复中有提到 遗漏的方法,并建议做一个文档管理工具 ,一细想是可以啊,之后就开始构思,最后大至需求如下,
因为都是下班后在家中花时间做的,时间有点短,有BUG是正常的,希望大家谅解,再一个对windows的文件权限,几乎是0接触所以把权限处理留到了后期,如果大家有关于文件夹权限处理的好文章,希望大家给我留言,好的东西需要分享,本篇会写一下几个功能点的思路与做法,算是对自己的总结,如果对本项目有兴趣的朋友请
最后如果您觉得,有什么地方做得不够好,或者您有什么建议 与 意见 请一定要指出! 在此非常感谢! &
一 工具功能点
1 以树形展示单个磁盘内所有文件夹子文件夹,与文件名
2 支持子文件夹的层级展开
3 右侧支持文本文档的预览(二期)
4 若是图片支持预览(二期)
&1 支持指定目录下的文件夹新增,(右键)
&2&支持指定目录下的文件夹删除(右键)
&3&支持指定目录下的文件夹,与文件的重命名((右键))
&4 支持指定目录下的文件夹与文件移动到另一指定的文件夹(托拽)
&5 支持指定目录下的文件夹批量删除
&6 支持指定目录下的文件搜索 (只要文件名匹配即可)(二期)
&7 文件夹与文件的访问权限处理
以上就是大至简单的需求,然后根据需求,选择了以下几个小插件
zTree:树形插件 个人觉得很不错,国内的插件,API文档解释很详细,至少我从来没用过树形插件的,比较容易的就上手了。
Layer:弹出层插件,使用简单,效果好,拿来即用
二 工具基本介绍
先上几张图 &新建文件夹,文件夹或文件重命名
删除文件或文件夹(支持批量删除)
以拖拽形式批量移动文件夹
三 功能实现讲解
3.1 加载文件夹树
  根据zTree需要的参数配置就行了,具体参数请大家看zTree的API吧,着重写一下加载时遇到的坑
实现思路:遍历指定路径下第一层所有文件夹与文件并组成对象序列化成Json并返回Json数据给zTree绑定
& & 刚开始想着一次性把所有的文件与文件夹都加载出来,然后用递归实现,但是因为我定义了一个类来保存文件的信息,而且是以嵌套的形式存的,这样的做法初看觉得
很有层次感到写递归时,却把自己坑了,也主要是以前没认真写过递归,导致这一方法纠结了一个晚上再加上午的一点时间,终于递归出来了,
然后一试验,浏览器直接死了,数量太大嵌套的太深,加载一次至少要40秒以上,于是果断放弃了,改为每次只加载一层
以下为保存数据的类,与加载的方法 , 这里只列出部分代码,具体代码在源码中都可找到
public class zTreeModel
public zTreeModel()
_isPrent = false;
_children = new List&zTreeModel&();
private bool _isP
private List&zTreeModel& _children = null;
/// &summary&
///根结点名字
/// &/summary&
public string rootFullName { get; set; }
/// &summary&
/// 父结点名称
/// &/summary&
public string pName { get; set; }
/// &summary&
/// 父结点全路径名称
/// &/summary&
public string pFullName { get; set; }
/// &summary&
/// 当前结点全路径名称
/// &/summary&
public string fullName { get; set; }
/// &summary&
/// 当前结点名称
/// &/summary&
public string name { get; set; }
/// &summary&
/// 是否为父结点
/// &/summary&
public bool isParent {
get { return _isP }
set { _isPrent = }
/// &summary&
/// 是否为顶层节点
/// &/summary&
public bool topNode { get; set; }
/// &summary&
/// 是否为文件 默认为False
/// &/summary&
public bool isFile { get; set; }
/// &summary&
/// 是否打开
/// &/summary&
public bool open { get; set; }
/// &summary&
/// 子结点
/// &/summary&
public List&zTreeModel& children
get { return _ }
set { _children = }
JavaScript
var zTreeObj,
setting = {
selectedMulti: true,
showLine: true
isMove: true,
inner:true//拖拽后为同级节点,
},//托拽操作配置
enable: true,//节点可编辑
showRemoveBtn: false,
showRenameBtn: false,
editNameSelectAll: true
parent:true //删除子节点后父节点不变为叶子节点
enable: true,
autoParam:["fullName"],
url: "/FileManager/GetSingleLevelNodes",
type: "POST",
treeNode: {
checked:true
// beforeExpand: zTreeBeforeExpand,//展开节点前的回调方法
beforeRename: zTreeBeforeRename,//重命名之前的回调方法
onRename: zTreeOnRename,//重命名
beforeRemove: zTreeBeforeRemove,//删除前回调方法
onRemove: zTreeRemove,//删除
beforeRightClick: zTreeBeforeRightClick,//右键方法前的回调
onRightClick: zTreeOnRightClick,//右键方法
beforeDrop: zTreeBeforeDrop,//用于捕获节点拖拽操作结束之前的事件回调函数,并且根据返回值确定是否允许此拖拽操作.如果返回 false,zTree 将恢复被拖拽的节点,也无法触发 onDrop 事件回调函数
onDrop: zTreeOnDrop,//拖拽操作结束的事件
beforeDrag: zTreeBeforeDrag//托拽前的方法
var zTreeNodes = "";
$(function () {
ReLoadTree();
function ReLoadTree() {
url: "/FileManager/GetDefaultFiles",
type: "POST",
async: false,
dataType: "json",
success: function (data) {
zTreeNodes =
zTreeObj = $.fn.zTree.init($("#tree"), setting, zTreeNodes);
public List&zTreeModel& GetDefaultFiles(string path)
zTreeModel treeModel = null;
List&zTreeModel&
treeModelList = new List&zTreeModel&();
if (Directory.Exists(path))
//获取子目录
DirectoryInfo
directory =
new DirectoryInfo(path);
var folders = directory.GetDirectories();
//遍历路径下文件夹
foreach (var folder in folders)
treeModel = new zTreeModel();
treeModel.pName = folder.Parent == null ? " " : folder.Parent.N
treeModel.pFullName = folder.Parent == null ? " " : folder.Parent.FullN
treeModel.rootFullName = folder.Root.FullN
treeModel.name = folder.N
treeModel.fullName = folder.FullN
treeModel.isParent = true;
treeModelList.Add(treeModel);
catch (UnauthorizedAccessException ex)//调用方没有所要求的权限。
return null;
//获取路径下文件
DirectoryInfo fileDirectory = new DirectoryInfo(path);
var files = fileDirectory.GetFiles();
foreach (var file in files)
treeModel = new zTreeModel();
treeModel.pName = file.Directory == null ? "" : file.Directory.N
treeModel.pFullName = file.DirectoryN
treeModel.rootFullName = file.Directory == null ? "" : file.Directory.Root.FullN
treeModel.name = file.N
treeModel.fullName = file.FullN
treeModel.isFile = true;
treeModelList.Add((treeModel));
catch (UnauthorizedAccessException ex) //调用方没有所要求的权限。
return null;
return treeModelL
3.2 新增文件夹节点
实现思路:弹出框写文件夹名,然后前台组装新节点的json数据,并把新节点对象传到Action中反序列化成对象,根据节点属性创建文件夹,如果已存在相同文件名则提示,否则正常创建
javascript&
1 //新增节点
function zTreeAddNode() {
var zTreeObj = $.fn.zTree.getZTreeObj("tree");
var parent = zTreeObj.getSelectedNodes()[0]; //把选中的节点当做父节点
if (parent == undefined) {
layer.alert('给新孩子找个父节点啊~~', 8);
return false;
} else if (parent.isParent == false) {
layer.alert('亲~只能选文件夹哦~', 8);
return false;
ShowDialog(parent, zTreeObj);
function ShowDialog(parent, zTreeObj) {
shade: [0.5, '#000', true], //遮罩
msg: '文件夹名:&input type="text" id="folderName"/&',
title: ['新建文件夹', true],
area: ['503px', '395px'],
btn: ['添加', '取消'],
yes: function(index) {
var name = $("#folderName").val();
if (name == "") {
layer.alert('啊喂~还没写名字呢~', 8);
return false;
//拼装新节点对象
var nodes = { "fullName": parent.fullName + " \\ " + name, "name": name, "pName": parent.pName, "pFullName": parent.pFullName, "isParent": true };
url: "/FileManager/AddNode",
type: "POST",
"node": JSON.stringify(nodes)
dataType: "json",
success: function(data) {
if (!data.Status) {
layer.alert(data.Message, 8);
layer.close(index);
return false;
zTreeObj.addNodes(parent, nodes);
layer.close(index);
no: function(index) {
layer.close(index);
public OperationResult CreateFolder(zTreeModel zTree, OperationResult operation)
DirectoryInfo directory = new DirectoryInfo(zTree.fullName);
if (directory.Exists)
operation.Status = false;
operation.Message = "文件夹已存在了哦~";
directory.Create();
3.3 &删除树上文件夹节点
& & &思路:取到选中节点,再取节点fullName 属性,(此属性保存了文件的全路径),把fullName异步传入Action后调用方法,递归删除文件夹,递归的方式是先遍历到最深层的子文件夹如果有遇到不可访问的文件则删除操作不能继续进行,并提示用户不能删除的文件夹名,如果都可访问则从最深层的子文件夹开始递归删除,代码如下
JavaScript
//删除节点
function zTreeRemove() {
var treeObj = $.fn.zTree.getZTreeObj("tree");
var node = treeObj.getSelectedNodes();
var isParents = false;
$.each(node, function(index, item) {
if (item.isParent) {
isParents = true;
if (isParents) {
var meg = "确定要把文件夹中所有文件都删了吗?不能恢复的哦~也不能怪我哦~";
deleteNodes(node, meg);
var meg = "确定要删除所以选中的文件吗?不能恢复的哦~";
deleteNodes(node, meg);
function deleteNodes(nodes, meg) {
shade: [0.5, '#000', true], //遮罩
title: '删除文件夹',
area: ['503px', '395px'],
btn: ['删除', '取消'],
yes: function(index) {
url: "/FileManager/DeleteNode",
type: "POST",
data: { "node": JSON.stringify(nodes) },
dataType: "json",
success: function(data) {
if (!data.Status) {
layer.alert(data.Message, 8);
var treeObj = $.fn.zTree.getZTreeObj("tree");
var selectedNodes = treeObj.getSelectedNodes();
for (var i = 0; i & selectedNodes. i++) {
treeObj.removeNode(selectedNodes[i]);
layer.close(index);
}, no: function(index) {
layer.close(index);
public OperationResult Delete(DirectoryInfo directory, OperationResult operation)
//从深层子目录开始遍历删除
DirectoryInfo[] childFolder = directory.GetDirectories();
if (operation.Status)
//有元素就遍历删除,没有则直接删除文件夹
if (childFolder.Any())
foreach (var directoryInfo in childFolder)
Delete(directoryInfo, operation);
FileInfo[] files = directoryInfo.GetFiles();
foreach (var fileInfo in files)
fileInfo.Delete();
directoryInfo.Delete();
catch (UnauthorizedAccessException ex)
operation.Status = false;
operation.Message = string.Format("{0}此文件夹没有权限访问!无法执行删除操作", directoryInfo.FullName);
//验证文件是否能删除
directory.Delete();
catch (UnauthorizedAccessException ex)
operation.Status = false;
operation.Message = string.Format("{0}此文件夹没有权限访问!无法执行删除操作", directory.FullName);
3.4 &右键方法&
思路:点击右键时触发右键事件,在事件方法中把事先写好的Html菜单展示出来并绑定相应的js事件,根结点没有删除与重命名操作,只能新增子节点
javaScript
//右键方法
function zTreeOnRightClick(event, treeId, treeNode) {
if (treeId == undefined) {
return false;
$("#rMenu").css({
top: event.clientY + "px",
left:event.clientX +"px",
display: "block",
"z-index": 1
if (treeNode.topNode) {
showItem(["#addFolder"]);
showItem(["#addFolder", "#reName", "#deleteFile"]);
//显示右键菜单
function showItem(itemArray) {
for (var i = 0; i & itemArray. i++) {
$(itemArray[i]).show();
$("#rMenu").hover(function() {
$("#addFolder").click(function() {
//alert("第一次添加!");
zTreeAddNode();
$("#rMenu").hide();
$("#reName").click(function() {
$("#rMenu").hide();
$("#deleteFile").click(function() {
zTreeRemove();
$("#rMenu").hide();
function() {
for (var j = 0; j & itemArray. j++) {
$(itemArray[j]).hide();
3.5 重命名
思路:触发重命名方法后会使节点处于编辑状态,失去焦点后自动保存,在保存时先要做验证没有相同的文件名,并刷新节点的属性
注意:因为要先验证文件名是否已存在,所以先要异步去检查,但是检查与执行重命名的方法都是异步的没法分先后,且方法都要用的zTree提供的方法,所以每次重命名后要重新加载一次整棵树 体验有点不太好
javascript
function zTreeBeforeRename(treeId, treeNode, newName, isCancel) {
//文件名长度不能超过260个字符(包括路径)
var zTreeObj = $.fn.zTree.getZTreeObj("tree");
if ((treeNode.fullName + newName).length & 260) {
layer.alert("啊喂~ 你文件名也太长了点吧!", 8);
zTreeObj.editName(treeNode);
var status = false;
var path = treeNode.pFullName + "\\" + newN
//判断新文件名是否已存在
url: "/FileManager/CheckRename",
async:false,
type: "POST",
"path": path,
"isParent": treeNode.isParent
dataType: "json",
success: function (data) {
status = data.S
if (!data.Status) {
layer.alert(data.Message, 8);
//阻止因Alter反复调用zTreeBeforeRename方法
//zTreeObj.editName(treeNode);
if (status) {
return true;
return false;
function Rename() {
var zTreeObj = $.fn.zTree.getZTreeObj("tree");
var nodes = zTreeObj.getSelectedNodes();//取到为选中节点数组
zTreeObj.editName(nodes[0]);//把第一个节点变为编辑状态
function zTreeOnRename(event, treeId, treeNode, isCancel) {
//把检查文件名放在此方法中
var zTreeObj = $.fn.zTree.getZTreeObj("tree");
var path = treeNode.fullN
var destPath = treeNode.pFullName + "\\" + treeNode.
var isParent = treeNode.isP
//重命名后,fullname,name 都要修改
url: "/FileManager/RenameFiles",
async:false,
type: "POST",
"path": path,
"destPath": destPath,
"isParent": isParent
dataType: "json",
success: function(data) {
if (data.Status) {
ReLoadTree();
//重命名后刷新父节点,更新子节点中的fullName等属性
//var selectNodes = zTreeObj.getSelectedNodes();
//var parent = selectNodes[0].getParentNode();
//zTreeObj.reAsyncChildNodes(parent, "refresh");
//检查文件名是否存在
public void CheckFileName(string path, bool isParent,OperationResult operation)
if (isParent)
if (Directory.Exists(path))
operation.Status = false;
operation.Message = "文件夹已经存在了哦!";
if (File.Exists(path))
operation.Status = false;
operation.Message = "文件已经存在了哦!";
public void RenameFileName(string path, string destPath, bool isParent, OperationResult operation)
if (isParent)
DirectoryInfo directory = new DirectoryInfo(path);
directory.MoveTo(destPath);
FileInfo file = new FileInfo(path);
file.MoveTo(destPath);
3.6 拖拽方法(移动文件夹,按Ctrl可多选)
思路:根节点不能被拖动,也不能拖为根节点,然后遍历选中的节点,并传到Action中反序列化成对象执行移动,并在移动后在前端把节点的属性pName fullName pFullName更新,避免重新加载树
javascript
//拖拽前的方法
function zTreeBeforeDrag(treeId, treeNodes) {
//根结点不能被移动,
for (var i = 0; i & treeNodes. i++) {
if (treeNodes[i].topNode) {
layer.alert("根结点不能被托动哦~", 8);
return false;
//捕获节点拖拽操作结束之前的事件回调函数,并且根据返回值确定是否允许此拖拽操作
//如果返回 false,zTree 将恢复被拖拽的节点,也无法触发 onDrop 事件回调函数
function zTreeBeforeDrop(treeId, treeNodes, targetNode, moveType) {
//不能拖拽为根节点
if ((targetNode == null || (moveType != "inner"))) {
return false;
if (!targetNode.isParent) {
layer.alert("只能托动到文件夹内哦~", 8);
return false;
url: "FileManager/MoveFiles",
async: false,
type: "POST",
"nodes": JSON.stringify(treeNodes),
"targetNode": JSON.stringify(targetNode)
dataType: "json",
success: function (data) {
if (!data.Status) {
layer.alert(data.Message, 8);
return false;
//节点拖动后要把的路径改为新路径
for (var i = 0; i & treeNodes. i++) {
treeNodes[i].fullName = targetNode.fullName + "\\" + treeNodes[i].
treeNodes[i].pName = targetNode.
treeNodes[i].pFullName = targetNode.fullN
public void
MoveFilesToFolder(List&zTreeModel& nodes, zTreeModel targetNode,OperationResult operation)
foreach (var node in nodes)
if (node.isParent)
DirectoryInfo directory = new DirectoryInfo(node.fullName);
if (Directory.Exists(targetNode.fullName))
//要移动的新地址
string newPath = targetNode.fullName + "\\" + node.
directory.MoveTo(newPath);
operation.Status = false;
operation.Message = string.Format("{0}文件夹不存在啊~!", node.fullName);
FileInfo file = new FileInfo(node.fullName);
if (Directory.Exists(targetNode.fullName))
string newPath = targetNode.fullName + "\\" + node.
file.MoveTo(newPath);
operation.Status = false;
operation.Message = string.Format("{0}文件夹不存在啊~!", node.fullName);
& & 虽然这个小工具功能并不强大,但至少是我从有想法到有行动到有成果的一个过程,并且我也享受这一过程,
在开发的过程中,了解了zTree的各种用法,对文件夹,文件的操作也有了更深入的了解,
如果您觉得这个工具有那么点意思 不妨点下推荐哦~您的推荐是我创作源源不断的动力
阅读(...) 评论()

我要回帖

更多关于 写代码时听的歌 的文章

 

随机推荐