zoukankan      html  css  js  c++  java
  • 文件夹管理工具(MVC+zTree+layer)(附源码)

    一 工具功能点

    一 展示
    1 以树形展示单个磁盘内所有文件夹子文件夹,与文件名
    2 支持子文件夹的层级展开
    3 右侧支持文本文档的预览(二期)
    4 若是图片支持预览(二期)
     
    二 操作
    1 支持指定目录下的文件夹新增,(右键)
    2 支持指定目录下的文件夹删除(右键)
    3 支持指定目录下的文件夹,与文件的重命名((右键))
    4 支持指定目录下的文件夹与文件移动到另一指定的文件夹(托拽)
    5 支持指定目录下的文件夹批量删除
    6 支持指定目录下的文件搜索 (只要文件名匹配即可)(二期)
    7 文件夹与文件的访问权限处理
     
    以上就是大至简单的需求,然后根据需求,选择了以下几个小插件
    zTree:树形插件 个人觉得很不错,国内的插件,API文档解释很详细,至少我从来没用过树形插件的,比较容易的就上手了。 zTree插件地址
    Layer:弹出层插件,使用简单,效果好,拿来即用   Layer插件地址
     

    二 工具基本介绍

     
    先上几张图  新建文件夹,文件夹或文件重命名
            
     
    删除文件或文件夹(支持批量删除)
     
     
    以拖拽形式批量移动文件夹
     
     
     
     

    三 功能实现讲解

     
    3.1 加载文件夹树
     
      根据zTree需要的参数配置就行了,具体参数请大家看zTree的API吧,着重写一下加载时遇到的坑
    实现思路:遍历指定路径下第一层所有文件夹与文件并组成对象序列化成Json并返回Json数据给zTree绑定
     
        刚开始想着一次性把所有的文件与文件夹都加载出来,然后用递归实现,但是因为我定义了一个类来保存文件的信息,而且是以嵌套的形式存的,这样的做法初看觉得
    很有层次感到写递归时,却把自己坑了,也主要是以前没认真写过递归,导致这一方法纠结了一个晚上再加上午的一点时间,终于递归出来了,
    然后一试验,浏览器直接死了,数量太大嵌套的太深,加载一次至少要40秒以上,于是果断放弃了,改为每次只加载一层
    以下为保存数据的类,与加载的方法 , 这里只列出部分代码,具体代码在源码中都可找到
     
    类设计
    复制代码
     1  public class zTreeModel
     2     {
     3         public zTreeModel()
     4         {
     5             _isPrent = false;
     6             _children = new List<zTreeModel>();
     7         }
     8 
     9         private bool _isPrent ;
    10         private List<zTreeModel> _children = null;
    11        
    12         /// <summary>
    13         ///根结点名字
    14         /// </summary>
    15         public string rootFullName { get; set; }
    16 
    17         /// <summary>
    18         /// 父结点名称
    19         /// </summary>
    20         public string pName { get; set; }
    21         /// <summary>
    22         /// 父结点全路径名称
    23         /// </summary>
    24         public string pFullName { get; set; }
    25 
    26         /// <summary>
    27         /// 当前结点全路径名称
    28         /// </summary>
    29         public string fullName { get; set; }
    30 
    31         /// <summary>
    32         /// 当前结点名称
    33         /// </summary>
    34         public string name { get; set; }
    35    
    36         /// <summary>
    37         /// 是否为父结点
    38         /// </summary>
    39         public bool isParent {
    40             get { return _isPrent; }
    41             set { _isPrent = value; }
    42         }
    43         /// <summary>
    44         /// 是否为顶层节点
    45         /// </summary>
    46         public bool topNode { get; set; }
    47 
    48         /// <summary>
    49         /// 是否为文件 默认为False 
    50         /// </summary>
    51         public bool isFile { get; set; }
    52 
    53         /// <summary>
    54         /// 是否打开
    55         /// </summary>
    56         public bool open { get; set; }
    57 
    58         /// <summary>
    59         /// 子结点
    60         /// </summary>
    61         public List<zTreeModel> children
    62         {
    63             get { return _children; }
    64             set { _children = value; }
    65         }
    66     }
    复制代码

    JavaScript

    复制代码
     1     var zTreeObj,
     2         setting = {
     3             view: {
     4                 selectedMulti: true,
     5                 showLine: true                
     6             },
     7             edit: {
     8                 drag: {
     9                     isMove: true,
    10                     inner:true//拖拽后为同级节点,
    11                 },//托拽操作配置
    12                 enable: true,//节点可编辑
    13                 showRemoveBtn: false,
    14                 showRenameBtn: false,
    15                 editNameSelectAll: true
    16             },
    17             data: {
    18                 keep: {
    19                     parent:true //删除子节点后父节点不变为叶子节点
    20                 },
    21                 
    22             },
    23             async: {
    24                 enable: true,
    25                 autoParam:["fullName"],
    26                 url: "/FileManager/GetSingleLevelNodes",
    27                 type: "POST",
    28                 
    29             },
    30             treeNode: {
    31                 checked:true
    32                     
    33             },
    34             callback:
    35             {
    36                // beforeExpand: zTreeBeforeExpand,//展开节点前的回调方法
    37 
    38                 beforeRename: zTreeBeforeRename,//重命名之前的回调方法
    39                 onRename: zTreeOnRename,//重命名
    40                 
    41                 beforeRemove: zTreeBeforeRemove,//删除前回调方法
    42                 onRemove: zTreeRemove,//删除
    43                 
    44                 beforeRightClick: zTreeBeforeRightClick,//右键方法前的回调
    45                 onRightClick: zTreeOnRightClick,//右键方法
    46                 
    47                 beforeDrop: zTreeBeforeDrop,//用于捕获节点拖拽操作结束之前的事件回调函数,并且根据返回值确定是否允许此拖拽操作.如果返回 false,zTree 将恢复被拖拽的节点,也无法触发 onDrop 事件回调函数
    48                 onDrop: zTreeOnDrop,//拖拽操作结束的事件
    49                 beforeDrag: zTreeBeforeDrag//托拽前的方法 
    50                 
    51            }
    52         };
    53        
    54     var zTreeNodes = "";
    55     $(function () {
    56         ReLoadTree();
    57     });
    58     
    59     function ReLoadTree() {
    60         $.ajax({
    61             url: "/FileManager/GetDefaultFiles",
    62             type: "POST",
    63             async: false,
    64             dataType: "json",
    65             success: function (data) {
    66                 zTreeNodes = data;
    67             }
    68         });
    69         zTreeObj = $.fn.zTree.init($("#tree"), setting, zTreeNodes);
    70 
    71     }
    复制代码

    C#

    复制代码
     1         public List<zTreeModel> GetDefaultFiles(string path)
     2         {
     3             zTreeModel treeModel = null;
     4             List<zTreeModel>  treeModelList = new List<zTreeModel>();
     5             if (Directory.Exists(path))
     6             {
     7                 //获取子目录
     8                 DirectoryInfo  directory =  new DirectoryInfo(path);
     9               
    10                 try
    11                 {
    12                     var folders = directory.GetDirectories();
    13                     //遍历路径下文件夹
    14                     foreach (var folder in folders)
    15                     {
    16                         treeModel = new zTreeModel();
    17                         treeModel.pName = folder.Parent == null ? " " : folder.Parent.Name;
    18                         treeModel.pFullName = folder.Parent == null ? " " : folder.Parent.FullName;
    19                         treeModel.rootFullName = folder.Root.FullName;
    20                         treeModel.name = folder.Name;
    21                         treeModel.fullName = folder.FullName;
    22                         treeModel.isParent = true;
    23                         treeModelList.Add(treeModel);
    24                     }
    25 
    26                 }
    27                 catch (UnauthorizedAccessException ex)//调用方没有所要求的权限。
    28                 {
    29                     return null;
    30                 }
    31 
    32                 //获取路径下文件 
    33                 DirectoryInfo fileDirectory = new DirectoryInfo(path);
    34                 
    35                 try
    36                 {
    37                     var files = fileDirectory.GetFiles();
    38                     foreach (var file in files)
    39                     {
    40                         treeModel = new zTreeModel();
    41                         treeModel.pName = file.Directory == null ? "" : file.Directory.Name;
    42                         treeModel.pFullName = file.DirectoryName;
    43                         treeModel.rootFullName = file.Directory == null ? "" : file.Directory.Root.FullName;
    44                         treeModel.name = file.Name;
    45                         treeModel.fullName = file.FullName;
    46                         treeModel.isFile = true;
    47                         treeModelList.Add((treeModel));
    48                     }
    49 
    50                 }
    51                 catch (UnauthorizedAccessException ex) //调用方没有所要求的权限。
    52                 {
    53                     return null;
    54                 }
    55             }
    56 
    57             return treeModelList;
    58 
    59         }
    复制代码

    3.2 新增文件夹节点

    实现思路:弹出框写文件夹名,然后前台组装新节点的json数据,并把新节点对象传到Action中反序列化成对象,根据节点属性创建文件夹,如果已存在相同文件名则提示,否则正常创建

    javascript

    复制代码
     1 //新增节点
     2     function zTreeAddNode() {
     3         var zTreeObj = $.fn.zTree.getZTreeObj("tree");
     4         var parent = zTreeObj.getSelectedNodes()[0]; //把选中的节点当做父节点 
     5         if (parent == undefined) {
     6             layer.alert('给新孩子找个父节点啊~~', 8);
     7             return false;
     8         } else if (parent.isParent == false) {
     9             layer.alert('亲~只能选文件夹哦~', 8);
    10             return false;
    11         }
    12 
    13         ShowDialog(parent, zTreeObj);
    14     }
    15 
    16     function ShowDialog(parent, zTreeObj) {
    17 
    18         $.layer({
    19             shade: [0.5, '#000', true], //遮罩
    20             dialog: {
    21                 msg: '文件夹名:<input type="text" id="folderName"/>',
    22                 title: ['新建文件夹', true],
    23                 btns: 2,
    24                 type: 1,
    25                 area: ['503px', '395px'],
    26                 btn: ['添加', '取消'],
    27                 yes: function(index) {
    28                  
    29                     var name = $("#folderName").val();
    30                     if (name == "") {
    31                         layer.alert('啊喂~还没写名字呢~', 8);
    32                         return false;
    33                     }
    34                     //拼装新节点对象
    35                     var nodes = { "fullName": parent.fullName + " \ " + name, "name": name, "pName": parent.pName, "pFullName": parent.pFullName, "isParent": true };
    36                     $.ajax({
    37                         url: "/FileManager/AddNode",
    38                         type: "POST",
    39                         data: {
    40                             "node": JSON.stringify(nodes)
    41                         },
    42                         dataType: "json",
    43                         success: function(data) {
    44                             if (!data.Status) {
    45                                 layer.alert(data.Message, 8);
    46                                 layer.close(index);
    47                                 return false;
    48                             }
    49                             zTreeObj.addNodes(parent, nodes);
    50                             layer.close(index);
    51                         }
    52                     });
    53 
    54                 },
    55                 no: function(index) {
    56                     layer.close(index);
    57                 }
    58             }
    59         });
    60 
    61     }
    复制代码

    C#

    复制代码
     1         public OperationResult CreateFolder(zTreeModel zTree, OperationResult operation)
     2         {
     3             DirectoryInfo directory = new DirectoryInfo(zTree.fullName);
     4             if (directory.Exists)
     5             {
     6                 operation.Status = false;
     7                 operation.Message = "文件夹已存在了哦~";
     8             }
     9             else
    10             {
    11                 directory.Create();
    12             }
    13             return operation;
    14         }
    复制代码

    3.3  删除树上文件夹节点

         思路:取到选中节点,再取节点fullName 属性,(此属性保存了文件的全路径),把fullName异步传入Action后调用方法,递归删除文件夹,递归的方式是先遍历到最深层的子文件夹如果有遇到不可访问的文件则删除操作不能继续进行,并提示用户不能删除的文件夹名,如果都可访问则从最深层的子文件夹开始递归删除,代码如下

    JavaScript

    复制代码
     1     //删除节点
     2     function zTreeRemove() {
     3         var treeObj = $.fn.zTree.getZTreeObj("tree");
     4         var node = treeObj.getSelectedNodes();
     5         var isParents = false;
     6         $.each(node, function(index, item) {
     7             if (item.isParent) {
     8                 isParents = true;
     9             }
    10         });
    11         if (isParents) {
    12             var meg = "确定要把文件夹中所有文件都删了吗?不能恢复的哦~也不能怪我哦~";
    13             deleteNodes(node, meg);
    14         } else {
    15             var meg = "确定要删除所以选中的文件吗?不能恢复的哦~";
    16             deleteNodes(node, meg);
    17         }
    18     }
    19     function deleteNodes(nodes, meg) {
    20         $.layer({
    21             shade: [0.5, '#000', true], //遮罩
    22             dialog: {
    23                 msg: meg,
    24                 title: '删除文件夹',
    25                 btns: 2,
    26                 type: 1,
    27                 area: ['503px', '395px'],
    28                 btn: ['删除', '取消'],
    29                 yes: function(index) {
    30                     $.ajax({
    31                         url: "/FileManager/DeleteNode",
    32                         type: "POST",
    33                         data: { "node": JSON.stringify(nodes) },
    34                         dataType: "json",
    35                         success: function(data) {
    36                             if (!data.Status) {
    37                                 layer.alert(data.Message, 8);
    38                             } else {
    39                                 var treeObj = $.fn.zTree.getZTreeObj("tree");
    40                                 var selectedNodes = treeObj.getSelectedNodes();
    41                                 for (var i = 0; i < selectedNodes.length; i++) {
    42                                     treeObj.removeNode(selectedNodes[i]);
    43                                 }
    44                             }
    45                         }
    46                     });
    47                     layer.close(index);
    48                 }, no: function(index) {
    49                     layer.close(index);
    50                 }
    51             }
    52             
    53         });
    54 
    55     }
    复制代码

    C#

    复制代码
     1         public OperationResult Delete(DirectoryInfo directory, OperationResult operation)
     2         {
     3             //从深层子目录开始遍历删除
     4             DirectoryInfo[] childFolder = directory.GetDirectories();
     5             
     6             if (operation.Status)
     7             {
     8                 //有元素就遍历删除,没有则直接删除文件夹
     9                 if (childFolder.Any())
    10                 {
    11                     foreach (var directoryInfo in childFolder)
    12                     {
    13                         Delete(directoryInfo, operation);
    14                         FileInfo[] files = directoryInfo.GetFiles();
    15                         try
    16                         {
    17                             foreach (var fileInfo in files)
    18                             {
    19                                 fileInfo.Delete();
    20                             }
    21                             directoryInfo.Delete();
    22                         }
    23                         catch (UnauthorizedAccessException ex)
    24                         {
    25                             operation.Status = false;
    26                             operation.Message = string.Format("{0}此文件夹没有权限访问!无法执行删除操作", directoryInfo.FullName);
    27                             return operation;
    28                         }
    29                     }
    30                 }
    31                 else
    32                 {
    33                     //验证文件是否能删除
    34                     try
    35                     {
    36                         directory.Delete();
    37                     }
    38                     catch (UnauthorizedAccessException ex)
    39                     {
    40                         operation.Status = false;
    41                         operation.Message = string.Format("{0}此文件夹没有权限访问!无法执行删除操作", directory.FullName);
    42                         return operation;
    43                     }
    44                 }
    45             }
    46             return operation;
    47         }
    复制代码

    3.4  右键方法

    思路:点击右键时触发右键事件,在事件方法中把事先写好的Html菜单展示出来并绑定相应的js事件,根结点没有删除与重命名操作,只能新增子节点

    javaScript

    复制代码
     1     //右键方法
     2     function zTreeOnRightClick(event, treeId, treeNode) {
     3         if (treeId == undefined) {
     4             return false;
     5         }
     6        
     7         $("#rMenu").css({
     8             top: event.clientY + "px",
     9             left:event.clientX +"px",
    10             display: "block",
    11             "z-index": 1
    12         });
    13 
    14         if (treeNode.topNode) {
    15             showItem(["#addFolder"]);
    16         } else {
    17             showItem(["#addFolder", "#reName", "#deleteFile"]);
    18         }
    19 
    20     }
    21     //显示右键菜单
    22     function showItem(itemArray) {
    23         
    24         for (var i = 0; i < itemArray.length; i++) {
    25 
    26             $(itemArray[i]).show();
    27         }
    28         $("#rMenu").hover(function() {
    29             $("#addFolder").click(function() {
    30                 //alert("第一次添加!");
    31                 zTreeAddNode();
    32                 $("#rMenu").hide();
    33             });
    34             $("#reName").click(function() {
    35                 Rename();
    36                 $("#rMenu").hide();
    37             });
    38             $("#deleteFile").click(function() {
    39                 zTreeRemove();
    40                 $("#rMenu").hide();
    41             });
    42         },
    43             function() {
    44                 for (var j = 0; j < itemArray.length; j++) {
    45                     $(itemArray[j]).hide();
    46                 }
    47             });
    48 
    49     }
    复制代码

    3.5 重命名

    思路:触发重命名方法后会使节点处于编辑状态,失去焦点后自动保存,在保存时先要做验证没有相同的文件名,并刷新节点的属性

    注意:因为要先验证文件名是否已存在,所以先要异步去检查,但是检查与执行重命名的方法都是异步的没法分先后,且方法都要用的zTree提供的方法,所以每次重命名后要重新加载一次整棵树 体验有点不太好

    javascript

    复制代码
     1  function zTreeBeforeRename(treeId, treeNode, newName, isCancel) {
     2         //文件名长度不能超过260个字符(包括路径)
     3         var zTreeObj = $.fn.zTree.getZTreeObj("tree");
     4         if ((treeNode.fullName + newName).length > 260) {
     5             layer.alert("啊喂~ 你文件名也太长了点吧!", 8);
     6             zTreeObj.editName(treeNode);
     7         }
     8         var status = false;
     9         var path = treeNode.pFullName + "\" + newName;
    10         //判断新文件名是否已存在
    11         $.ajax({
    12             url: "/FileManager/CheckRename",
    13             async:false,
    14             type: "POST",
    15             data: {
    16                 "path": path,
    17                 "isParent": treeNode.isParent
    18             },
    19             dataType: "json",
    20             success: function (data) {
    21                 status = data.Status;
    22                 if (!data.Status) {
    23                     layer.alert(data.Message, 8);
    24                     //阻止因Alter反复调用zTreeBeforeRename方法
    25                     //zTreeObj.editName(treeNode);
    26                     //return false;
    27                 } else {
    28                     //return true;
    29                 }
    30             }
    31         });
    32        
    33         if (status) {
    34             return true;
    35         } else {
    36             return false;
    37         }
    38 
    39     }
    40 
    41     function Rename() {
    42         var zTreeObj = $.fn.zTree.getZTreeObj("tree");
    43         var nodes = zTreeObj.getSelectedNodes();//取到为选中节点数组
    44         zTreeObj.editName(nodes[0]);//把第一个节点变为编辑状态
    45 
    46     }
    47 
    48     //重命名
    49     function zTreeOnRename(event, treeId, treeNode, isCancel) {
    50 
    51         //把检查文件名放在此方法中
    52 
    53         var zTreeObj = $.fn.zTree.getZTreeObj("tree");
    54       
    55         var path = treeNode.fullName;
    56         var destPath = treeNode.pFullName + "\" + treeNode.name;
    57         var isParent = treeNode.isParent;
    58         //重命名后,fullname,name 都要修改
    59         $.ajax({
    60             url: "/FileManager/RenameFiles",
    61             async:false,
    62             type: "POST",
    63             data: {
    64                 "path": path,
    65                 "destPath": destPath,
    66                 "isParent": isParent
    67             },
    68             dataType: "json",
    69             success: function(data) {
    70                 if (data.Status) {
    71                     
    72                     ReLoadTree();
    73 
    74                     //重命名后刷新父节点,更新子节点中的fullName等属性
    75                     //var selectNodes = zTreeObj.getSelectedNodes();
    76                     //var parent = selectNodes[0].getParentNode();
    77                     //zTreeObj.reAsyncChildNodes(parent, "refresh");
    78                 }
    79             }
    80         });
    81 
    82 
    83     }
    复制代码

    C#

    复制代码
     1  //检查文件名是否存在
     2         public void CheckFileName(string path, bool isParent,OperationResult operation)
     3         {
     4             if (isParent)
     5             {
     6                 if (Directory.Exists(path))
     7                 {
     8                     operation.Status = false;
     9                     operation.Message = "文件夹已经存在了哦!";
    10                 }
    11             }
    12             else
    13             {
    14                 if (File.Exists(path))
    15                 {
    16                     operation.Status = false;
    17                     operation.Message = "文件已经存在了哦!";
    18                 }
    19             }
    20         }
    21         //重命名
    22         public void RenameFileName(string path, string destPath, bool isParent, OperationResult operation)
    23         {
    24             if (isParent)
    25             {
    26                 DirectoryInfo directory = new DirectoryInfo(path);
    27                 directory.MoveTo(destPath);
    28             }
    29             else
    30             {
    31                 FileInfo file = new FileInfo(path);
    32                 file.MoveTo(destPath);
    33             }
    34         }
    复制代码

    3.6 拖拽方法(移动文件夹,按Ctrl可多选)

    思路:根节点不能被拖动,也不能拖为根节点,然后遍历选中的节点,并传到Action中反序列化成对象执行移动,并在移动后在前端把节点的属性pName fullName pFullName更新,避免重新加载树

    javascript

    复制代码
     1     //拖拽前的方法 
     2     function zTreeBeforeDrag(treeId, treeNodes) {
     3         //根结点不能被移动,
     4         for (var i = 0; i < treeNodes.length; i++) {
     5             if (treeNodes[i].topNode) {
     6                 layer.alert("根结点不能被托动哦~", 8);
     7                 return false;
     8             }
     9         }
    10     }
    11     //捕获节点拖拽操作结束之前的事件回调函数,并且根据返回值确定是否允许此拖拽操作
    12     //如果返回 false,zTree 将恢复被拖拽的节点,也无法触发 onDrop 事件回调函数
    13 
    14     function zTreeBeforeDrop(treeId, treeNodes, targetNode, moveType) {
    15         //不能拖拽为根节点
    16         if ((targetNode == null || (moveType != "inner"))) {
    17             return false;
    18         }
    19         if (!targetNode.isParent) {
    20             layer.alert("只能托动到文件夹内哦~", 8);
    21             return false;
    22         }
    23        
    24         $.ajax({
    25             url: "FileManager/MoveFiles",
    26             async: false,
    27             type: "POST",
    28             data: {
    29                 "nodes": JSON.stringify(treeNodes),
    30                 "targetNode": JSON.stringify(targetNode)
    31             },
    32             dataType: "json",
    33             success: function (data) {
    34                 if (!data.Status) {
    35                     layer.alert(data.Message, 8);
    36                     return false;
    37                 } else {
    38                     //节点拖动后要把的路径改为新路径
    39                     for (var i = 0; i < treeNodes.length; i++) {
    40                         treeNodes[i].fullName = targetNode.fullName + "\" + treeNodes[i].name;
    41                         treeNodes[i].pName = targetNode.name;
    42                         treeNodes[i].pFullName = targetNode.fullName;
    43                     }
    44                 }
    45             }
    46         });
    47     }
    复制代码

    C#

    复制代码
     1  public void  MoveFilesToFolder(List<zTreeModel> nodes, zTreeModel targetNode,OperationResult operation)
     2         {
     3             
     4 
     5             foreach (var node in nodes)
     6             {
     7                 //文件夹
     8                 if (node.isParent)
     9                 {
    10                     DirectoryInfo directory = new DirectoryInfo(node.fullName);
    11                     if (Directory.Exists(targetNode.fullName))
    12                     {
    13                         //要移动的新地址
    14                         string newPath = targetNode.fullName + "\" + node.name;
    15                         directory.MoveTo(newPath);
    16                     }
    17                     else
    18                     {
    19                         operation.Status = false;
    20                         operation.Message = string.Format("{0}文件夹不存在啊~!", node.fullName);
    21                     }
    22 
    23                 }//文件
    24                 else
    25                 {
    26                     FileInfo file = new FileInfo(node.fullName);
    27                     if (Directory.Exists(targetNode.fullName))
    28                     {
    29                         string newPath = targetNode.fullName + "\" + node.name;
    30                         file.MoveTo(newPath);
    31                     }
    32                     else
    33                     {
    34                         operation.Status = false;
    35                         operation.Message = string.Format("{0}文件夹不存在啊~!", node.fullName);
    36                     }
    37                 }
    38 
    39             }
    40           
    41         }
    复制代码

    四 总结

        虽然这个小工具功能并不强大,但至少是我从有想法到有行动到有成果的一个过程,并且我也享受这一过程,

    在开发的过程中,了解了zTree的各种用法,对文件夹,文件的操作也有了更深入的了解,

    如果您觉得这个工具有那么点意思 不妨点下推荐哦~您的推荐是我创作源源不断的动力

    源文件

  • 相关阅读:
    监视用户是保存用户编辑还是放弃参照编辑
    AutoCAD: 添加鼠标快捷键/鼠标右键
    C# List<T>集合布尔运算
    List<T>的用法详解
    天正的坑
    C#札记
    AUTOCAD2013 以上利用ACCORECONSOLE+ SCR后台批量清理图纸
    BaiduSitemap
    三一邮件群发
    Windows+IIS+Mysql+php安装
  • 原文地址:https://www.cnblogs.com/jameslif/p/3342978.html
Copyright © 2011-2022 走看看