Browse Source

feat: 清单库增加复制、粘贴整块

vian 3 months atrás
parent
commit
a0cee3fc0d

File diff suppressed because it is too large
+ 7 - 0
lib/localforage/localforage.min.js


+ 3 - 3
modules/bills_lib/models/bills_lib_interfaces.js

@@ -13,7 +13,7 @@ let moment = require("moment");
 let billsGuidanceLib = mongoose.model("std_billsGuidance_lib");
 const engLibModel = mongoose.model("engineering_lib");
 let uuid = require("uuid");
-let billsLibDao = function () {};
+let billsLibDao = function () { };
 
 billsLibDao.prototype.copyLib = async function (userName, libName, fromLibId) {
   const libData = await this.createStdBillsLibSync(userName, libName);
@@ -396,13 +396,13 @@ billsLibDao.prototype.createBills = function (cbillsData, callback) {
   let newBills = [];
   for (let bill of insertBills) {
     newBills.push({
-      ...bill,
       code: "",
       name: "",
       unit: "",
       ruleText: "",
       Expression: "",
       recharge: "",
+      ...bill,
       deleted: false,
     });
   }
@@ -4815,7 +4815,7 @@ billsLibDao.prototype.importBills = async function (billsLibId, sheetData) {
       recharge: "",
     };
     let jobData =
-        typeof rowData[4] !== "undefined" ? getDivideData(rowData[4]) : [],
+      typeof rowData[4] !== "undefined" ? getDivideData(rowData[4]) : [],
       itemData =
         typeof rowData[5] !== "undefined" ? getDivideData(rowData[5]) : [];
     bills.jobData = jobData;

+ 133 - 106
public/web/id_tree.js

@@ -122,12 +122,12 @@ var idTree = {
             },
             addUpdateDataForParent: function (datas, nodes, pid) {
                 nodes.forEach(function (node) {
-                    datas.push({type: 'update', data: node.tree.getDataTemplate(node.getID(), pid, node.getNextSiblingID())});
+                    datas.push({ type: 'update', data: node.tree.getDataTemplate(node.getID(), pid, node.getNextSiblingID()) });
                 });
             },
             addUpdateDataForNextSibling: function (datas, node, nid) {
                 if (node) {
-                    datas.push({type: 'update', data: node.tree.getDataTemplate(node.getID(), node.getParentID(), nid)});
+                    datas.push({ type: 'update', data: node.tree.getDataTemplate(node.getID(), node.getParentID(), nid) });
                 }
             }
         };
@@ -222,14 +222,14 @@ var idTree = {
 
 
         // 获取节点所有后代节点
-        Node.prototype.getPosterity = function() {
+        Node.prototype.getPosterity = function () {
             let posterity = [];
             getNodes(this.children);
             return posterity;
             function getNodes(nodes) {
                 for (let node of nodes) {
                     posterity.push(node);
-                    if (node.children.length > 0){
+                    if (node.children.length > 0) {
                         getNodes(node.children);
                     }
                 }
@@ -237,12 +237,12 @@ var idTree = {
         };
 
         // 担心链有问题,preSibling不靠谱的话,按照显示顺序算preSibling
-        Node.prototype.prevNode = function() {
+        Node.prototype.prevNode = function () {
             const parent = this.parent || this.tree.roots;
             if (!parent) {
                 return null;
             }
-            const children = parent === this.tree.roots ? this.tree.roots :  parent.children;
+            const children = parent === this.tree.roots ? this.tree.roots : parent.children;
             const index = children.indexOf(this);
             return children[index - 1] || null;
         }
@@ -297,12 +297,12 @@ var idTree = {
                     tools.addUpdateDataForNextSibling(data, this.preSibling, this.tree.setting.rootId);
                 }
                 tools.addUpdateDataForNextSibling(data, this.parent, this.getID());
-                data.push({type: 'update', data: this.tree.getDataTemplate(this.getID(), this.parent.getParentID(), this.parent.getNextSiblingID())});
+                data.push({ type: 'update', data: this.tree.getDataTemplate(this.getID(), this.parent.getParentID(), this.parent.getNextSiblingID()) });
             }
             return data;
         };
         Node.prototype.upLevel = function () {
-            var result = {success: false, updateDatas: []};
+            var result = { success: false, updateDatas: [] };
             var iIndex = this.parent.children.indexOf(this), orgParent = this.parent, newNextSibling = this.parent.nextSibling;
             if (this.canUpLevel) {
                 // NextSiblings become child
@@ -329,7 +329,7 @@ var idTree = {
                     tools.addUpdateDataForNextSibling(data, this.preSibling.lastChild(), this.getID());
                 }
                 tools.addUpdateDataForNextSibling(data, this.preSibling, this.getNextSiblingID());
-                data.push({type: 'update', data: this.tree.getDataTemplate(this.getID(), this.preSibling.getID(), this.tree.setting.rootId)});
+                data.push({ type: 'update', data: this.tree.getDataTemplate(this.getID(), this.preSibling.getID(), this.tree.setting.rootId) });
             }
             return data;
         };
@@ -533,7 +533,7 @@ var idTree = {
         Tree.prototype.insert = function (parentID, nextSiblingID) {
             var newID = this.newNodeID(), node = null, data = {};
             var parent = parentID == -1 ? null : this.nodes[this.prefix + parentID];
-            var nextSibling = nextSiblingID == -1 ? null: this.nodes[this.prefix + nextSiblingID];
+            var nextSibling = nextSiblingID == -1 ? null : this.nodes[this.prefix + nextSiblingID];
             if (newID !== -1) {
                 data = {};
                 data[this.setting.id] = newID;
@@ -551,24 +551,24 @@ var idTree = {
             }
             return node;
         };
-        Tree.prototype.m_insert = function (datas,parentID, nextSiblingID) {
-           // var newID = this.newNodeID(), node = null, data = {};
+        Tree.prototype.m_insert = function (datas, parentID, nextSiblingID) {
+            // var newID = this.newNodeID(), node = null, data = {};
             var parent = parentID == -1 ? null : this.nodes[this.prefix + parentID];
-            var nextSibling = nextSiblingID == -1 ? null: this.nodes[this.prefix + nextSiblingID];
-            let preInsertNode = null,nodes = [];
-            for(let d of datas){
-                let node = new Node(this,d.data);
-                if(preInsertNode == null){
+            var nextSibling = nextSiblingID == -1 ? null : this.nodes[this.prefix + nextSiblingID];
+            let preInsertNode = null, nodes = [];
+            for (let d of datas) {
+                let node = new Node(this, d.data);
+                if (preInsertNode == null) {
                     if (nextSibling) {
                         tools.addNodes(this, parent, [node], nextSibling.siblingIndex());
                     } else {
                         tools.addNodes(this, parent, [node]);
                     }
-                }else {
+                } else {
                     tools.addNodes(this, parent, [node], preInsertNode.siblingIndex());
                 }
                 this.nodes[this.prefix + d.data.ID] = node;
-                if(preInsertNode) node.setNextSibling(preInsertNode);
+                if (preInsertNode) node.setNextSibling(preInsertNode);
                 preInsertNode = node;
                 nodes.push(node);
             }
@@ -581,7 +581,7 @@ var idTree = {
         Tree.prototype.insertByID = function (newID, parentID, nextSiblingID) {
             var node = null, data = {};
             var parent = parentID == -1 ? null : this.nodes[this.prefix + parentID];
-            var nextSibling = nextSiblingID == -1 ? null: this.nodes[this.prefix + nextSiblingID];
+            var nextSibling = nextSiblingID == -1 ? null : this.nodes[this.prefix + nextSiblingID];
             if (newID) {
                 data = {};
                 data[this.setting.id] = newID;
@@ -602,9 +602,9 @@ var idTree = {
             var data = [];
             var newID = this.newNodeID();
             var parent = parentID == -1 ? null : this.nodes[this.prefix + parentID];
-            var nextSibling = nextSiblingID == -1 ? null: this.nodes[this.prefix + nextSiblingID];
+            var nextSibling = nextSiblingID == -1 ? null : this.nodes[this.prefix + nextSiblingID];
             if (newID !== -1) {
-                data.push({type: 'new', data: this.getDataTemplate(newID, parent ? parent.getID() : this.setting.rootId, nextSibling ? nextSibling.getID() : this.setting.rootId)});
+                data.push({ type: 'new', data: this.getDataTemplate(newID, parent ? parent.getID() : this.setting.rootId, nextSibling ? nextSibling.getID() : this.setting.rootId) });
 
                 if (nextSibling && nextSibling.preSibling) {
                     tools.addUpdateDataForNextSibling(data, nextSibling.preSibling, newID);
@@ -617,17 +617,17 @@ var idTree = {
             return data;
         };
         //插入多行
-        Tree.prototype.getInsertDatas = function (rowCount,parentID, nextSiblingID) {
-            let data = [],preInsertID = null,lastID;
+        Tree.prototype.getInsertDatas = function (rowCount, parentID, nextSiblingID) {
+            let data = [], preInsertID = null, lastID;
             let parent = parentID == -1 ? null : this.nodes[this.prefix + parentID];
-            let nextSibling = nextSiblingID == -1 ? null: this.nodes[this.prefix + nextSiblingID];
-            for(let i=0;i<rowCount ;i++){//先插入的在最后,后插的在最前
+            let nextSibling = nextSiblingID == -1 ? null : this.nodes[this.prefix + nextSiblingID];
+            for (let i = 0; i < rowCount; i++) {//先插入的在最后,后插的在最前
                 let newID = this.newNodeID();
-                if(newID !== -1){
-                    if(preInsertID == null){//说明是第一个插入的
-                        data.push({type: 'new', data: this.getDataTemplate(newID, parent ? parent.getID() : this.setting.rootId, nextSibling ? nextSibling.getID() : this.setting.rootId)});
-                    }else {//其它的下一节点ID取上一个插入的节点
-                        data.push({type: 'new', data: this.getDataTemplate(newID, parent ? parent.getID() : this.setting.rootId, preInsertID)});
+                if (newID !== -1) {
+                    if (preInsertID == null) {//说明是第一个插入的
+                        data.push({ type: 'new', data: this.getDataTemplate(newID, parent ? parent.getID() : this.setting.rootId, nextSibling ? nextSibling.getID() : this.setting.rootId) });
+                    } else {//其它的下一节点ID取上一个插入的节点
+                        data.push({ type: 'new', data: this.getDataTemplate(newID, parent ? parent.getID() : this.setting.rootId, preInsertID) });
                     }
                     this.maxNodeID(newID);
                     preInsertID = newID;
@@ -656,25 +656,34 @@ var idTree = {
                 } else {
                     tools.addNodes(this, parent, [node]);
                 }
-                this.nodes[this.prefix +  data[this.setting.id]] = node;
+                this.nodes[this.prefix + data[this.setting.id]] = node;
                 tools.sortTreeItems(this);
-                this.maxNodeID( data[this.setting.id]);
+                this.maxNodeID(data[this.setting.id]);
                 return node;
             }
         };
+        // 插入离散节点
+        Tree.prototype.insertByDatas = function (datas) {
+            const nodes = [];
+            datas.forEach(item => {
+                const node = this.insertByData(item, item.ParentID, item.NextSiblingID);
+                nodes.push(node);
+            });
+            return nodes;
+        };
         //批量新增节点到节点后项,节点已有树结构数据
         Tree.prototype.insertDatasTo = function (preData, datas) {
             let rst = [];
-            for(let data of datas){
+            for (let data of datas) {
                 this.nodes[this.prefix + data.ID] = new Node(this, data.ID);
                 this.nodes[this.prefix + data.ID]['data'] = data;
                 rst.push(this.nodes[this.prefix + data.ID]);
             }
-            for(let data of datas){
+            for (let data of datas) {
                 let node = this.nodes[this.prefix + data.ID];
                 let parent = data.ParentID == -1 ? null : this.nodes[this.prefix + data.ParentID];
                 node.parent = parent;
-                if(!parent){
+                if (!parent) {
                     this.roots.push(node);
                 }
                 else {
@@ -682,14 +691,14 @@ var idTree = {
                 }
                 let next = data.NextSiblingID == -1 ? null : this.nodes[this.prefix + data.NextSiblingID];
                 node.nextSibling = next;
-                if(next){
+                if (next) {
                     next.preSibling = node;
                 }
             }
             let preNode = this.nodes[this.prefix + preData.ID];
-            if(preNode){
+            if (preNode) {
                 preNode.nextSibling = this.nodes[this.prefix + preData.NextSiblingID] ? this.nodes[this.prefix + preData.NextSiblingID] : null;
-                if(preNode.nextSibling){
+                if (preNode.nextSibling) {
                     preNode.nextSibling.preSibling = preNode;
                 }
             }
@@ -700,7 +709,7 @@ var idTree = {
         };
         Tree.prototype.delete = function (node) {
             var success = false, that = this;
-            if(node) success = that.m_delete([node]);
+            if (node) success = that.m_delete([node]);
             return success;
         };
         Tree.prototype.m_delete = function (nodes) {
@@ -711,7 +720,7 @@ var idTree = {
                     deleteIdIndex(node.children);
                 })
             };
-            for(let n of nodes){
+            for (let n of nodes) {
                 deleteIdIndex([n]);
                 if (n.preSibling) {
                     n.preSibling.setNextSibling(n.nextSibling);
@@ -734,76 +743,76 @@ var idTree = {
             let o_next = o_parent.nextSibling;//父节点的下一节点
             let o_pre = nodes[0].preSibling;
             let o_children = o_parent.children;//旧的所有兄弟节点
-            let children = o_parent.parent?o_parent.parent.children:this.roots;//新的兄弟节点
+            let children = o_parent.parent ? o_parent.parent.children : this.roots;//新的兄弟节点
             let last;
             let lastNext;//最后一个选中节点后面的所有兄弟节点变成最后一个节点的子节点
-            for(let i = 0; i<nodes.length;i++){
+            for (let i = 0; i < nodes.length; i++) {
                 let index = children.indexOf(o_parent) + 1;
-                children.splice(index + i,0,nodes[i]);//往新的父节点的子节点插入节点
+                children.splice(index + i, 0, nodes[i]);//往新的父节点的子节点插入节点
                 o_children.splice(nodes[i].siblingIndex(), 1);//旧的数组删除节点
-                if(i == 0){//第一个节点变成原来父节点的下一节点
+                if (i == 0) {//第一个节点变成原来父节点的下一节点
                     o_parent.setNextSibling(nodes[i]);
-                    if(o_pre) o_pre.setNextSibling(null); //第一个选中节点的前一节点的下一节点设置为空
+                    if (o_pre) o_pre.setNextSibling(null); //第一个选中节点的前一节点的下一节点设置为空
                 }
                 nodes[i].setParent(o_parent.parent);
                 last = nodes[i];
                 lastNext = last.nextSibling;
             }
             last.setNextSibling(o_next);//最后一个选中的节点的下一个节点设置为原父节点的下一节点
-            if(lastNext){
+            if (lastNext) {
                 let t_index = o_children.indexOf(lastNext);
-                for(let j = t_index;j <o_children.length;j++ ){//剩下的添加为最后一个选中节点的子节点
+                for (let j = t_index; j < o_children.length; j++) {//剩下的添加为最后一个选中节点的子节点
                     last.addChild(o_children[j]);
                 }
-                if(o_children.length > t_index)  o_children.splice(t_index, o_children.length - t_index);//从原先的children中移除
+                if (o_children.length > t_index) o_children.splice(t_index, o_children.length - t_index);//从原先的children中移除
             }
-            if (o_parent.parent&& !o_parent.parent.expanded)  o_parent.parent.setExpanded(true);
+            if (o_parent.parent && !o_parent.parent.expanded) o_parent.parent.setExpanded(true);
             tools.sortTreeItems(this);
             return true;
         };
         Tree.prototype.getUpLevelDatas = function (nodes) {
             //getParentID
-            let o_parentID =  nodes[0].getParentID();
+            let o_parentID = nodes[0].getParentID();
             let o_children = nodes[0].parent.children;//旧的所有兄弟节点
             let o_pre = nodes[0].preSibling;
             let new_parentID = nodes[0].parent.getParentID();
             let o_nextID = nodes[0].parent.getNextSiblingID();
-            let dataMap = {},updateDatas=[],lastID,lastNext;
-            for(let i = 0; i<nodes.length;i++){
-                if(i == 0){
-                    dataMap[o_parentID] = {"ID":o_parentID,"NextSiblingID":nodes[i].getID()};
-                    if(o_pre) dataMap[o_pre.getID()] = {"ID":o_pre.getID(),"NextSiblingID":-1}; //nodes[i].preSibling.setNextSibling(null);
+            let dataMap = {}, updateDatas = [], lastID, lastNext;
+            for (let i = 0; i < nodes.length; i++) {
+                if (i == 0) {
+                    dataMap[o_parentID] = { "ID": o_parentID, "NextSiblingID": nodes[i].getID() };
+                    if (o_pre) dataMap[o_pre.getID()] = { "ID": o_pre.getID(), "NextSiblingID": -1 }; //nodes[i].preSibling.setNextSibling(null);
                 }
-                dataMap[nodes[i].getID()] = {"ID":nodes[i].getID(),"ParentID":new_parentID};
+                dataMap[nodes[i].getID()] = { "ID": nodes[i].getID(), "ParentID": new_parentID };
                 lastID = nodes[i].getID();
                 lastNext = nodes[i].nextSibling;
             }
-            if(dataMap[lastID] !== undefined){
+            if (dataMap[lastID] !== undefined) {
                 dataMap[lastID].NextSiblingID = o_nextID;
             }
-            if(lastNext){
+            if (lastNext) {
                 let t_index = o_children.indexOf(lastNext);
-                for(let j = t_index;j <o_children.length;j++ ){//剩下的添加为最后一个选中节点的子节点
-                    dataMap[o_children[j].getID()] = {"ID":o_children[j].getID(),"ParentID":lastID};
+                for (let j = t_index; j < o_children.length; j++) {//剩下的添加为最后一个选中节点的子节点
+                    dataMap[o_children[j].getID()] = { "ID": o_children[j].getID(), "ParentID": lastID };
                 }
             }
-            for(let key in dataMap){
-                updateDatas.push({type: 'update', data:dataMap[key]});
+            for (let key in dataMap) {
+                updateDatas.push({ type: 'update', data: dataMap[key] });
             }
             return updateDatas;
         };
         Tree.prototype.m_downLevel = function (nodes) {
-            let pre = nodes[0].preSibling ; //第一个节点的前一节点,即会成为新的父节点
-            let next ;//最后一个节点的后一节点,会成为pre 的下一个节点
-            let last ;//选中的最后一个节点,nextSibling要设置为0
-            for( let n of nodes){
+            let pre = nodes[0].preSibling; //第一个节点的前一节点,即会成为新的父节点
+            let next;//最后一个节点的后一节点,会成为pre 的下一个节点
+            let last;//选中的最后一个节点,nextSibling要设置为0
+            for (let n of nodes) {
                 next = n.nextSibling;
                 last = n;
-                let  children = n.parent?n.parent.children:this.roots;
+                let children = n.parent ? n.parent.children : this.roots;
                 children.splice(n.siblingIndex(), 1);
                 pre.addChild(n);
             }
-            if (!pre.expanded)  pre.setExpanded(true);
+            if (!pre.expanded) pre.setExpanded(true);
             pre.setNextSibling(next);
             last.nextSibling = null;
             tools.sortTreeItems(this);
@@ -811,25 +820,25 @@ var idTree = {
         };
 
         Tree.prototype.getDownLevelDatas = function (nodes) {
-            let dataMap = {},updateDatas=[],nextID,last;//注释同m_downLevel 方法
+            let dataMap = {}, updateDatas = [], nextID, last;//注释同m_downLevel 方法
             let newParent = nodes[0].preSibling;//{"type":"update","data":{"ID":3,"ParentID":-1,"NextSiblingID":5}}
-            let newPre = newParent.children && newParent.children.length > 0 ? newParent.children[newParent.children.length -1]:null;
-            if(newPre){ //如果新的父节点有子节点,则把新的父节点的最后一个子节点的下一节点的值改成第一个选中节点的ID
-                dataMap[newPre.getID()] = {"ID":newPre.getID(),"NextSiblingID":nodes[0].getID()}
+            let newPre = newParent.children && newParent.children.length > 0 ? newParent.children[newParent.children.length - 1] : null;
+            if (newPre) { //如果新的父节点有子节点,则把新的父节点的最后一个子节点的下一节点的值改成第一个选中节点的ID
+                dataMap[newPre.getID()] = { "ID": newPre.getID(), "NextSiblingID": nodes[0].getID() }
             }
-            for(let n of nodes){
+            for (let n of nodes) {
                 nextID = n.getNextSiblingID();
                 last = n;
-                dataMap[n.getID()] = {"ID":n.getID(),"ParentID":newParent.getID()}//修改父ID;
+                dataMap[n.getID()] = { "ID": n.getID(), "ParentID": newParent.getID() }//修改父ID;
             }
-            dataMap[newParent.getID()] = {"ID":newParent.getID(),"NextSiblingID":nextID}//设置新的父节点的下一个节点ID;
-            if(dataMap[last.getID()]!==undefined){//把最后一个节点的下一个节点ID变成-1
+            dataMap[newParent.getID()] = { "ID": newParent.getID(), "NextSiblingID": nextID }//设置新的父节点的下一个节点ID;
+            if (dataMap[last.getID()] !== undefined) {//把最后一个节点的下一个节点ID变成-1
                 dataMap[last.getID()].NextSiblingID = -1
-            }else {
-                dataMap[last.getID()] = {"ID":last.getID(),"NextSiblingID":-1};
+            } else {
+                dataMap[last.getID()] = { "ID": last.getID(), "NextSiblingID": -1 };
             }
-            for(let key in dataMap){
-                updateDatas.push({type: 'update', data:dataMap[key]});
+            for (let key in dataMap) {
+                updateDatas.push({ type: 'update', data: dataMap[key] });
             }
             return updateDatas;
         };
@@ -840,7 +849,7 @@ var idTree = {
                 nodes.forEach(function (node) {
                     var delData = {};
                     delData[node.tree.setting.id] = node.getID();
-                    datas.push({type: 'delete', data: delData});
+                    datas.push({ type: 'delete', data: delData });
                     addUpdateDataForDelete(datas, node.children);
                 })
             };
@@ -852,32 +861,32 @@ var idTree = {
             }
             return data;
         };
-        Tree.prototype.getDeleteDatas = function (deleteMap,deleteNodes){//批量删除
+        Tree.prototype.getDeleteDatas = function (deleteMap, deleteNodes) {//批量删除
             let datas = [];
-            addDeleteDatas(datas,deleteNodes);
-            for(let d of deleteNodes){
-                addPreUpdateData(datas,deleteMap,d.preSibling,d.nextSibling);
-            }
-           function addPreUpdateData(updateDatas,map,preSibling,nextSibling) {
-               if(preSibling && (map[preSibling.getID()] == undefined || map[preSibling.getID()] == null)){
-                   if(nextSibling){
-                      if(map[nextSibling.getID()]){//如果下一个节点也是要删除的,则再往下顺延
-                          addPreUpdateData(updateDatas,map,preSibling,nextSibling.nextSibling);
-                      }else {
-                          updateDatas.push({type: 'update', data: preSibling.tree.getDataTemplate(preSibling.getID(), preSibling.getParentID(),nextSibling.getID())});
-                      }
-                   }else {
-                       updateDatas.push({type: 'update', data: preSibling.tree.getDataTemplate(preSibling.getID(), preSibling.getParentID(),-1)});
-                   }
-               }
-           }
-
-            function addDeleteDatas(dataArray,nodes) {
-                for(let n of nodes){
+            addDeleteDatas(datas, deleteNodes);
+            for (let d of deleteNodes) {
+                addPreUpdateData(datas, deleteMap, d.preSibling, d.nextSibling);
+            }
+            function addPreUpdateData(updateDatas, map, preSibling, nextSibling) {
+                if (preSibling && (map[preSibling.getID()] == undefined || map[preSibling.getID()] == null)) {
+                    if (nextSibling) {
+                        if (map[nextSibling.getID()]) {//如果下一个节点也是要删除的,则再往下顺延
+                            addPreUpdateData(updateDatas, map, preSibling, nextSibling.nextSibling);
+                        } else {
+                            updateDatas.push({ type: 'update', data: preSibling.tree.getDataTemplate(preSibling.getID(), preSibling.getParentID(), nextSibling.getID()) });
+                        }
+                    } else {
+                        updateDatas.push({ type: 'update', data: preSibling.tree.getDataTemplate(preSibling.getID(), preSibling.getParentID(), -1) });
+                    }
+                }
+            }
+
+            function addDeleteDatas(dataArray, nodes) {
+                for (let n of nodes) {
                     let delData = {};
                     delData[n.tree.setting.id] = n.getID();
-                    dataArray.push({type: 'delete', data: delData});
-                    addDeleteDatas(dataArray,n.children);
+                    dataArray.push({ type: 'delete', data: delData });
+                    addDeleteDatas(dataArray, n.children);
                 }
             }
             return datas;
@@ -899,7 +908,25 @@ var idTree = {
             this.event[eventName] = eventFun;
         };
 
+        Tree.prototype.resetID = function (items, IDFunc) {
+            const IDMap = {};
+            items.forEach(item => {
+                IDMap[item.ID] = IDFunc();
+            });
+            items.forEach(item => {
+                if (IDMap[item.ID]) {
+                    item.ID = IDMap[item.ID];
+                }
+                if (IDMap[item.ParentID]) {
+                    item.ParentID = IDMap[item.ParentID];
+                }
+                if (IDMap[item.NextSiblingID]) {
+                    item.NextSiblingID = IDMap[item.NextSiblingID];
+                }
+            });
+        };
+
         return new Tree(setting);
     },
-    updateType: {update: 'update', new: 'new', delete: 'delete'}
+    updateType: { update: 'update', new: 'new', delete: 'delete' }
 };

+ 24 - 2
public/web/tree_sheet/tree_sheet_controller.js

@@ -91,6 +91,24 @@ var TREE_SHEET_CONTROLLER = {
             return nodes;
         };
 
+        controller.prototype.insertByDatas = function (datas) {
+            let nodes = [], that = this, sels = this.sheet.getSelections();
+            if (this.tree) {
+                nodes = this.tree.insertByDatas(datas);
+            }
+            let length = nodes.length;
+            if (nodes.length > 0) {
+                TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
+                    that.sheet.addRows(nodes[length - 1].serialNo(), length);
+                    TREE_SHEET_HELPER.refreshTreeNodeData(that.setting, that.sheet, nodes, false);
+                    that.setTreeSelected(nodes[length - 1]);
+                    that.sheet.setSelection(nodes[length - 1].serialNo(), sels[0].col, 1, 1);
+                    //that.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
+                });
+            }
+            return nodes;
+        };
+
 
         controller.prototype.insertByID = function (ID) {
             var newNode = null, that = this, sels = this.sheet.getSelections();
@@ -165,6 +183,7 @@ var TREE_SHEET_CONTROLLER = {
         };
         controller.prototype.m_delete = function (nodes) {
             var that = this, sels = this.sheet.getSelections();
+            debugger;
             if (nodes.length > 0) {
                 if (this.tree.m_delete(nodes)) {
                     TREE_SHEET_HELPER.massOperationSheet(this.sheet, function () {
@@ -173,8 +192,9 @@ var TREE_SHEET_CONTROLLER = {
                             rowCount = rowCount + node.posterityCount() + 1;
                         }
                         that.sheet.deleteRows(sels[0].row, rowCount);
-                        that.setTreeSelected(that.tree.items[sels[0].row]);
-                        that.sheet.setSelection(sels[0].row, sels[0].col, 1, sels[0].colCount);
+                        const locateRow = that.tree.items.length <= sels[0].row ? that.tree.items.length - 1 : sels[0].row;
+                        that.setTreeSelected(that.tree.items[locateRow]);
+                        that.sheet.setSelection(locateRow, sels[0].col, 1, sels[0].colCount);
                     });
                 }
             }
@@ -194,6 +214,7 @@ var TREE_SHEET_CONTROLLER = {
             }
         };
         controller.prototype.downLevel = function () {
+            debugger;
             var that = this;
             if (this.tree.selected) {
                 if (this.tree.selected.downLevel()) {
@@ -281,6 +302,7 @@ var TREE_SHEET_CONTROLLER = {
                 this.event.beforeTreeSelectedChange(this.tree.selected);
             }
             this.tree.selected = node;
+            console.log(node);
             if (this.event.refreshBaseActn) {
                 this.event.refreshBaseActn(this.tree);
             }

+ 10 - 1
web/maintain/bills_lib/html/qingdan.html

@@ -9,6 +9,7 @@
     <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
     <link rel="stylesheet" href="/web/maintain/bills_lib/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css">
     <!--spread-->
     <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.sc.css">
     <link rel="stylesheet" href="/lib/codemirror/codemirror.css">
@@ -350,16 +351,21 @@
     <%include ../../../common/html/uploadImg.html %>
     <!-- JS. -->
     <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
+    <script src = "/lib/localforage/localforage.min.js"></script>
+    <script src="/public/common_util.js"></script>
     <script>GC.Spread.Sheets.LicenseKey =  '<%- LicenseKey %>';</script>
     <script src="/public/web/uuid.js"></script>
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
+    <script src="/lib/jquery-contextmenu/jquery.contextMenu.min.js"></script>
+    <script src="/lib/jquery-contextmenu/jquery.ui.position.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
     <script src="/web/maintain/bills_lib/scripts/global.js"></script>
     <script src="/public/web/PerfectLoad.js"></script>
     <script src="/public/web/common_ajax.js"></script>
     <script src="/public/web/lock_util.js"></script>
     <script src="/public/web/sheet/sheet_common.js"></script>
+    <script type="text/javascript" src="/public/web/sheet/sheet_data_helper.js"></script>
     <script src="/web/maintain/bills_lib/scripts/set_sheets.js"></script>
     <script src="/web/maintain/bills_lib/scripts/bills_lib_ajax.js"></script>
     <!--idTree-->
@@ -615,6 +621,7 @@
         let nameList = BillsFixedFlagList.map((data) => data.name);
         let comboCol = setting.cols.findIndex((data) => data.data.field === 'fixedFlag');
         setCombo(billsSheet, comboCol, nameList);
+        onContextmenuOpr(billsSpread, controller);
     }
 
     function switchFcs(controller, billsSheet, billsSpread, jobsSheet, designsSheet, itemsSheet){
@@ -981,10 +988,12 @@
 
     function bindPasteBills(controller, sheet, setting){
         sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, function (sender, args) {
+            debugger;
             sheetBillsDatas = tools.getsheetDatas(sheet, 'bills', controller);
             let maxCol = args.cellRange.col + args.cellRange.colCount - 1;
+            let maxRow = args.cellRange.row + args.cellRange.rowCount - 1;
             //复制的列数超过正确的列数,不可复制
-            if(maxCol >= billsLibSetting.cols.length){
+            if(maxCol >= billsLibSetting.cols.length || maxRow >= controller.tree.items.length){
                 args.cancel = true;
             }
         });

+ 278 - 46
web/maintain/bills_lib/scripts/db_controller.js

@@ -47,6 +47,275 @@ function getNewBIlls(controller, rowCount, billsLibId) {
   return { insertBills, updatePreData };
 }
 
+// 创建清单
+const createBills = (controller, btn, insertBills, updatePreData, isInsertByDatas) => {
+  billsAjax.createBills(
+    userAccount,
+    billsLibId,
+    updatePreData,
+    insertBills,
+    function () {
+      if (updatePreData) {
+        const node = controller.tree.findNode(updatePreData.ID);
+        if (node) {
+          Object.assign(node.data, updatePreData);
+        }
+      }
+      // 显示的时候,类别和固定ID转换为名称显示
+      const kindMap = {};
+      billKindComboList.forEach(item => {
+        kindMap[item.value] = item.name;
+      });
+      const flagMap = {};
+      BillsFixedFlagList.forEach(item => {
+        flagMap[item.value] = item.name;
+      });
+      insertBills.forEach(bill => {
+        if (bill.kind) {
+          bill.kind = kindMap[bill.kind] || '';
+        }
+        if (bill.fixedFlag) {
+          bill.fixedFlag = flagMap[bill.fixedFlag] || '';
+        }
+      })
+      const treeData = insertBills.map((item) => ({
+        type: "new",
+        data: item,
+      }));
+      const newNodes = isInsertByDatas ? controller.insertByDatas(insertBills) : controller.m_insert(treeData);
+      newNodes.forEach(n => {
+        n.jobs = [];
+        n.items = [];
+        n.designs = [];
+        controller.sheet.setTag(
+          n.serialNo(),
+          0,
+          n.getID()
+        );
+      });
+      sheetBillsDatas = tools.getsheetDatas(
+        controller.sheet,
+        "bills",
+        controller
+      );
+      if (btn) {
+        tools.btnAction(btn);
+        btn.attr("doing", "false");
+      }
+      controller.sheet.getParent().focus(true);
+    }
+  );
+}
+
+// 获取需要复制的节点(与第一个节点同层的所有节点,包括后代)
+const getCopyNodes = (controller) => {
+  const { tree, sheet } = controller;
+  const selection = sheet.getSelections()[0];
+  const nodes = [];
+  const firstNode = tree.items[selection.row];
+  if (!firstNode) {
+    return [];
+  }
+  const firstNodeDepth = firstNode.depth();
+  for (let i = 0; i < selection.rowCount; i++) {
+    const row = selection.row + i;
+    const node = tree.items[row];
+    if (node && node.depth() === firstNodeDepth) {
+      nodes.push(node);
+    }
+  }
+  const rst = [];
+  nodes.forEach(node => {
+    const allNodes = [node, ...node.getPosterity()];
+    allNodes.forEach(n => {
+      if (!rst.includes(n)) {
+        rst.push(n);
+      }
+    })
+  });
+  return rst;
+}
+
+// 复制整块
+const copyBlock = async (controller) => {
+  try {
+    $.bootstrapLoading.start();
+    const nodes = getCopyNodes(controller);
+    const bills = [];
+    nodes.forEach(node => {
+      const bill = {};
+      Object.keys(node.data).forEach(key => {
+        if (typeof node.data[key] !== 'object') {
+          bill[key] = node.data[key];
+          bill.ID = node.getID();
+          bill.ParentID = node.getParentID();
+          bill.NexSiblingID = node.getNextSiblingID();
+        }
+      });
+      bills.push(bill);
+    });
+    await localforage.setItem('billsBlock', bills);
+    console.log(bills);
+  } catch (error) {
+    alert(error.message);
+  }
+  $.bootstrapLoading.end();
+}
+
+// 设置节点的前三层信息
+const setPasteSectionInfo = (tree, bills) => {
+  const IDMap = {};
+  tree.items.forEach(item => {
+    IDMap[item.getID()] = { ID: item.getID(), ParentID: item.getParentID(), NexSiblingID: item.getNextSiblingID() }; // 树操作后可能有缓存问题,data里的ID还没变
+  });
+  bills.forEach(bill => {
+    IDMap[bill.ID] = bill;
+  });
+  const getThreeParentIDs = (bill) => {
+    const parentIDs = [];
+    let cur = bill;
+    for (let i = 0; i < 3; i++) {
+      const parent = IDMap[cur.ParentID];
+      if (parent) {
+        parentIDs.push(parent.ID);
+        cur = parent;
+      } else {
+        break;
+      }
+    }
+    return parentIDs.reverse();
+  };
+  bills.forEach(bill => {
+    const parentIDs = getThreeParentIDs(bill);
+    const sectionInfo = { first: parentIDs[0] || null, second: parentIDs[1] || null, third: parentIDs[2] || null };
+    bill.sectionInfo = sectionInfo;
+  });
+}
+
+// 获取粘贴整块数据
+const getPasteData = async (controller) => {
+  const bills = await localforage.getItem('billsBlock');
+  if (!bills || !bills.length) {
+    throw new Error('请先复制整块!');
+  }
+  const { tree } = controller;
+  const selected = tree.selected;
+  if (!selected) {
+    throw new Error('请选中节点!');
+  }
+  tree.resetID(bills, uuid.v1);
+  // 粘贴到选中节点的最末子项
+  let updatePreData = null;
+  const lastChild = selected.lastChild();
+  const firstBill = bills[0];
+  if (lastChild) {
+    updatePreData = { ID: lastChild.getID(), NextSiblingID: firstBill.ID };
+  }
+  let lastRoot = firstBill;
+  const kindMap = {};
+  billKindComboList.forEach(item => {
+    kindMap[item.name] = item.value;
+  });
+  const flagMap = {};
+  BillsFixedFlagList.forEach(item => {
+    flagMap[item.name] = item.value;
+  });
+  const firstParentID = firstBill.ParentID;
+  bills.forEach(bill => {
+    bill.billsLibId = billsLibId;
+    bill.jobs = [];
+    bill.items = [];
+    bill.designs = [];
+    if (bill.kind) {
+      bill.kind = kindMap[bill.kind] || undefined;
+    }
+    if (bill.fixedFlag) {
+      bill.fixedFlag = flagMap[bill.fixedFlag] || undefined;
+    }
+    if (bill.ParentID === firstParentID) {
+      bill.ParentID = selected.getID();
+      lastRoot = bill;
+    }
+  });
+  if (lastRoot) {
+    lastRoot.NexSiblingID = -1;
+  }
+  setPasteSectionInfo(tree, bills);
+  return { insertBills: bills, updatePreData };
+}
+
+// 粘贴整块
+const pasteBlock = async (controller) => {
+  try {
+    $.bootstrapLoading.end();
+    const { insertBills, updatePreData } = await getPasteData(controller);
+    if (insertBills.length) {
+      createBills(controller, undefined, insertBills, updatePreData, true);
+    }
+    controller.event.refreshBaseActn(controller.tree);
+  } catch (error) {
+    alert(error.message);
+  }
+  $.bootstrapLoading.end();
+}
+
+
+// 右键
+const onContextmenuOpr = (workBook, controller) => {
+  //右键菜单
+  $.contextMenu({
+    selector: "#spreadBills",
+    build: function ($triggerElement, e) {
+      //控制允许右键菜单在哪个位置出现
+      let target = SheetDataHelper.safeRightClickSelection(
+        $triggerElement,
+        e,
+        workBook
+      );
+      let bill = controller.tree.items[target.row] || null;
+      controller.setTreeSelected(bill);
+      if (target.hitTestType === 3) {
+        return {
+          callback: function () { },
+          items: {
+            copyBlock: {
+              name: "复制整块",
+              disabled: function () {
+                const inValidCell =
+                  !commonUtil.isDef(target.row) ||
+                  !commonUtil.isDef(target.col);
+                const inValidData = target.row >= controller.tree.items.length;
+                return locked || inValidCell || inValidData;
+              },
+              icon: "fa-copy",
+              callback: function (key, opt) {
+                copyBlock(controller);
+              },
+            },
+            pasteBlock: {
+              name: "粘贴整块",
+              disabled: function () {
+                const inValidCell =
+                  !commonUtil.isDef(target.row) ||
+                  !commonUtil.isDef(target.col);
+                const inValidData = target.row >= controller.tree.items.length;
+                return locked || inValidCell || inValidData;
+              },
+              icon: "fa-paste",
+              callback: function (key, opt) {
+                pasteBlock(controller);
+              },
+            },
+          },
+        };
+      } else {
+        return false;
+      }
+    },
+  });
+};
+
+
 var dbController = {
   controller: null,
   currentEditData: null,
@@ -58,44 +327,7 @@ var dbController = {
       rowCount,
       billsLibId
     );
-    billsAjax.createBills(
-      userAccount,
-      billsLibId,
-      updatePreData,
-      insertBills,
-      function () {
-        if (updatePreData) {
-          const node = controller.tree.findNode(updatePreData.ID);
-          if (node) {
-            Object.assign(node.data, updatePreData);
-          }
-        }
-
-        const treeData = insertBills.map((item) => ({
-          type: "new",
-          data: item,
-        }));
-        const newNodes = controller.m_insert(treeData);
-        newNodes.forEach(n => {
-          n.jobs = [];
-          n.items = [];
-          console.log(n.serialNo(), n.getID());
-          controller.sheet.setTag(
-            n.serialNo(),
-            0,
-            n.getID()
-          );
-        });
-        sheetBillsDatas = tools.getsheetDatas(
-          controller.sheet,
-          "bills",
-          controller
-        );
-        tools.btnAction(btn);
-        btn.attr("doing", "false");
-        controller.sheet.getParent().focus(true);
-      }
-    );
+    createBills(controller, btn, insertBills, updatePreData);
   },
 
   upLevel: function (controller, btn) {
@@ -179,8 +411,8 @@ var dbController = {
         );
 
         billsAjax.upLevel(userAccount, billsLibId, updateData, function () {
-          //tools.btnAction(btn);
-          //btn.attr('doing', 'false');
+          tools.btnAction(btn);
+          btn.attr('doing', 'false');
           for (let upLevelNode of selNodes) {
             controller.setTreeSelected(upLevelNode);
             controller.upLevel();
@@ -196,8 +428,8 @@ var dbController = {
             billsAjax.updateSectionInfo(
               tools.getUpdateSectionData(toUpSectionNodes),
               function () {
-                tools.btnAction(btn);
-                btn.attr("doing", "false");
+                /* tools.btnAction(btn);
+                btn.attr("doing", "false"); */
               }
             );
           }
@@ -253,8 +485,8 @@ var dbController = {
         );
 
         billsAjax.downLevel(userAccount, billsLibId, updateData, function () {
-          //tools.btnAction(btn);
-          //btn.attr('doing', 'false');
+          tools.btnAction(btn);
+          btn.attr('doing', 'false');
           for (let downNode of selNodes) {
             controller.setTreeSelected(downNode);
             controller.downLevel();
@@ -270,8 +502,8 @@ var dbController = {
             billsAjax.updateSectionInfo(
               tools.getUpdateSectionData(toUpSectionNodes),
               function () {
-                tools.btnAction(btn);
-                btn.attr("doing", "false");
+                /* tools.btnAction(btn);
+                btn.attr("doing", "false"); */
               }
             );
           }