Explorar o código

台账分解,重做复制粘贴,保证兼容只读

MaiXinRong %!s(int64=5) %!d(string=hai) anos
pai
achega
97f1c0d134

+ 162 - 31
app/public/js/ledger.js

@@ -16,8 +16,32 @@ function getTenderId() {
 }
 
 const copyBlockTag = 'zh.calc.copyBlock';
+const invalidFields = {
+    parent: ['sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp', 'deal_qty', 'deal_tp', 'unit_price'],
+    gcl: ['dgn_qty1', 'dgn_qty2'],
+    posCode: ['b_code'],
+    posCalc: ['sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp'],
+};
 
 $(document).ready(function() {
+    // 提示窗
+    toastr.options = {
+        "closeButton": false,
+        "debug": false,
+        "newestOnTop": false,
+        "progressBar": false,
+        "positionClass": "toast-top-center",
+        "preventDuplicates": false,
+        "onclick": null,
+        "showDuration": "300",
+        "hideDuration": "1000",
+        "timeOut": "5000",
+        "extendedTimeOut": "1000",
+        "showEasing": "swing",
+        "hideEasing": "linear",
+        "showMethod": "fadeIn",
+        "hideMethod": "fadeOut"
+    };
     autoFlashHeight();
     // 初始化台账
     const ledgerSpread = SpreadJsObj.createNewSpread($('#ledger-spread')[0]);
@@ -93,7 +117,7 @@ $(document).ready(function() {
                     const rNode = sheet.zh_tree.nodes[sel.row + r];
                     if (rNode.level > node.level) continue;
                     if ((rNode.level < node.level) || (rNode.level === node.level && rNode.pid !== node.pid)) {
-                        toast('请选择同一清单下的节点,进行该操作');
+                        toastr.error('请选择同一清单下的节点,进行该操作');
                         return;
                     }
                     count += 1;
@@ -369,7 +393,7 @@ $(document).ready(function() {
                         if (!node.children || node.children.length ===0) {
                             const lPos = pos.getLedgerPos(node.id);
                             if (lPos && lPos.length > 0) {
-                                toast('清单含有部位明细,请在部位明细输入数量', 'error');
+                                toastr.error('清单含有部位明细,请在部位明细输入数量');
                                 SpreadJsObj.reLoadRowData(info.sheet, info.row);
                                 return;
                             }
@@ -378,7 +402,7 @@ $(document).ready(function() {
                     if (col.field === 'b_code' && (info.editingText === '' || !info.editingText)) {
                         const lPos = pos.getLedgerPos(node.id);
                         if (lPos && lPos.length > 0) {
-                            toast('清单含有部位明细,请先删除部位明细,再删除清单编号', 'error');
+                            toastr.error('清单含有部位明细,请先删除部位明细,再删除清单编号');
                             SpreadJsObj.reLoadRowData(info.sheet, info.row);
                             return;
                         }
@@ -425,7 +449,7 @@ $(document).ready(function() {
                             if (lPos && lPos.length > 0) {
                                 if (value === '' && colSetting.field === 'b_code') {
                                     if (!bHint) {
-                                        toast('清单含有部位明细,请先删除部位明细,再删除清单编号', 'warning');
+                                        toastr.warning('清单含有部位明细,请先删除部位明细,再删除清单编号');
                                         bHint = true;
                                     }
                                     continue;
@@ -434,7 +458,7 @@ $(document).ready(function() {
                                     colSetting.field === 'sjcl_qty' || colSetting.field === 'sjcl_tp' ||
                                     colSetting.field === 'qtcl_qty' || colSetting.field === 'qtcl_tp') {
                                     if (!bHint) {
-                                        toast('清单含有部位明细,数量金额根据部位明细汇总计算所得,不可编辑', 'warning');
+                                        toastr.warning('清单含有部位明细,数量金额根据部位明细汇总计算所得,不可编辑');
                                         bHint = true;
                                     }
                                     continue;
@@ -473,6 +497,90 @@ $(document).ready(function() {
                 }
             }
         },
+        clipboardPasting: function (e, info) {
+            const sheet = info.sheet, tree = info.sheet.zh_tree, setting = info.sheet.zh_setting;
+            console.log(info);
+            info.cancel = true;
+            if (!setting || !tree) return;
+            const pasteData = info.pasteData.html
+                ? SpreadJsObj.analysisPasteHtml(info.pasteData.html)
+                : (info.pasteData.text === ''
+                    ? SpreadJsObj.Clipboard.getAnalysisPasteText()
+                    : SpreadJsObj.analysisPasteText(info.pasteData.text));
+            let bParentHint = false, bGclHint = false, bCodeHint = false, bQtyHint = false, bNumHint = false;
+            const datas = [], filterNodes = [];
+            for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                const curRow = info.cellRange.row + iRow;
+                const node = tree.nodes[curRow];
+                if (!node) continue;
+
+                let bPaste = false;
+                const data = info.sheet.zh_tree.getNodeKeyData(node);
+                for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
+                    const curCol = info.cellRange.col + iCol;
+                    const colSetting = info.sheet.zh_setting.cols[curCol];
+                    const value = pasteData[iRow][iCol];
+                    const lPos = pos.getLedgerPos(node.id);
+                    if (node.children && node.children.length > 0 && invalidFields.parent.indexOf(colSetting.field) >= 0) {
+                        if (!bParentHint) bParentHint = true;
+                        continue;
+                    }
+                    if (!_.isEmpty(node.b_code) && invalidFields.gcl.indexOf(colSetting.field) >= 0) {
+                        if (!bGclHint) bGclHint = true;
+                        continue;
+                    }
+                    if (lPos && lPos.length > 0) {
+                        if (value === '' && invalidFields.posCode.indexOf(colSetting.field) >= 0) {
+                            if (!bCodeHint) bCodeHint = true;
+                            continue;
+                        }
+                        if (invalidFields.posCalc.indexOf(colSetting.field) >= 0) {
+                            if (!bQtyHint) bQtyHint = true;
+                            continue;
+                        }
+                    }
+                    if (colSetting.type === 'Number') {
+                        const num = _.toNumber(value);
+                        if (num) {
+                            data[colSetting.field] = num;
+                            bPaste = true;
+                        } else {
+                            bNumHint = true;
+                        }
+                    } else {
+                        data[colSetting.field] = value;
+                        bPaste = true;
+                    }
+                }
+                if (bPaste) {
+                    datas.push(data);
+                } else {
+                    filterNodes.push(node);
+                }
+            }
+            const hint = [];
+            if (bParentHint) hint.push('含有子项的清单,不可粘贴数量、单价、金额');
+            if (bGclHint) hint.push('工程量清单,不可粘贴设计数量');
+            if (bQtyHint) hint.push('含有部位明细的清单,不可粘贴数量');
+            if (bCodeHint) hint.push('含有部位明细的清单,清单编号不可粘贴空值');
+            if (bNumHint) hint.push('单价、数量等应输入数字');
+            // if (hint.length > 0) hint.unshift('复制粘贴的数据中,存在非法数据,已过滤:');
+            // if (hint.length > 0) toastr.warning(hint.join('</br>'));
+            if (hint.length > 0) toastr.warning('复制粘贴的数据中,存在非法数据,已过滤');
+            if (datas.length > 0) {
+                postData(window.location.pathname + '/update', {postType: 'update', postData: datas}, function (result) {
+                    const refreshNode = tree.loadPostData(result);
+                    if (refreshNode.update) {
+                        refreshNode.update = refreshNode.update.concat(filterNodes);
+                    }
+                    treeOperationObj.refreshTree(info.sheet, refreshNode);
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                });
+            } else {
+                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+            }
+        },
         /**
          * 删除按钮响应事件
          * @param sheet
@@ -500,9 +608,9 @@ $(document).ready(function() {
                                 if (lPos && lPos.length > 0) {
                                     if (!bHint) {
                                         if (col.field === 'code') {
-                                            toast('清单含有部位明细,请先删除部位明细,再删除清单编号', 'warning');
+                                            toastr.warning('清单含有部位明细,请先删除部位明细,再删除清单编号');
                                         } else {
-                                            toast('清单含有部位明细,数量金额根据部位明细汇总计算所得,不可删除', 'warning');
+                                            toastr.warning('清单含有部位明细,数量金额根据部位明细汇总计算所得,不可删除');
                                         }
                                         bHint = true;
                                     }
@@ -575,7 +683,7 @@ $(document).ready(function() {
         cut: function (sheet, sel, callback) {
             if (!sheet || !sel) return;
             if (sel.colCount >= sheet.zh_setting.cols.length) {
-                toast('请勿选中整行剪切', 'warnning');
+                toastr.warning('请勿选中整行剪切');
                 return;
             }
 
@@ -591,13 +699,13 @@ $(document).ready(function() {
                             col.field === 'qtcl_qty' || col.field === 'qtcl_tp') {
                             const lPos = pos.getLedgerPos(node.id);
                             if (lPos && lPos.length > 0) {
-                                toast('不可剪切', 'warning');
+                                toastr.error('不可剪切');
                                 return;
                             }
                         }
                         const style = sheet.getStyle(iRow, iCol);
                         if (style.locked) {
-                            toast('不可剪切', 'warning');
+                            toastr.error('不可剪切');
                             return;
                         }
                         const colSetting = sheet.zh_setting.cols[iCol];
@@ -615,6 +723,28 @@ $(document).ready(function() {
                 });
             }
         },
+        editStarting(e, info) {
+            if (!info.sheet.zh_setting || !info.sheet.zh_tree) return;
+            const col = info.sheet.zh_setting.cols[info.col];
+            const node = info.sheet.zh_tree.nodes[info.row];
+            switch (col.field) {
+                case 'unit_price':
+                case 'sgfh_qty':
+                case 'sgfh_tp':
+                case 'sjcl_qty':
+                case 'sjcl_tp':
+                case 'qtcl_qty':
+                case 'qtcl_tp':
+                case 'deal_qty':
+                case 'deal_tp':
+                    info.cancel = node.children && node.children.length > 0;
+                    break;
+                case 'dgn_qty1':
+                case 'dgn_qty2':
+                    info.cancel = !_.isEmpty(node.b_code);
+                    break;
+            }
+        }
     };
     // 绑定事件
     ledgerSpread.bind(GC.Spread.Sheets.Events.SelectionChanged, treeOperationObj.selectionChanged);
@@ -624,15 +754,16 @@ $(document).ready(function() {
             treeOperationObj.refreshOperationValid(info.sheet, info.newSelections);
         });
         ledgerSpread.bind(GC.Spread.Sheets.Events.EditEnded, treeOperationObj.editEnded);
-        ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardPasted, treeOperationObj.clipboardPasted);
+        //ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardPasted, treeOperationObj.clipboardPasted);
         SpreadJsObj.addDeleteBind(ledgerSpread, treeOperationObj.deletePress);
         ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardChanging, function (e, info) {
-            //info.cancel = true;
             const copyText = SpreadJsObj.getFilterCopyText(info.sheet);
-            copyToClipboard(copyText);
-        });
-        ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardPasting, function (e, info) {
+            //console.log(info.copyData);
+            SpreadJsObj.Clipboard.setCopyData(copyText);
+            //copyToClipboard(copyText);
         });
+        ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardPasting, treeOperationObj.clipboardPasting);
+        ledgerSpread.bind(spreadNS.Events.EditStarting, treeOperationObj.editStarting);
         SpreadJsObj.addCutEvents(ledgerSpread, treeOperationObj.cut);
 
         // 绑定 删除等 顶部按钮
@@ -759,7 +890,7 @@ $(document).ready(function() {
                         while (iRow < sel.row + sel.rowCount) {
                             const node = sheet.zh_tree.nodes[iRow];
                             if (node.ledger_pid !== pid) {
-                                toast('error: 仅可同时选中同层节点', 'error', 'exclamation-circle');
+                                toastr.error('仅可同时选中同层节点');
                                 return;
                             }
                             copyBlockList.push(node.ledger_id);
@@ -896,15 +1027,15 @@ $(document).ready(function() {
                 //const node = treeOperationObj.getSelectNode(ledgerSpread.getActiveSheet());
                 const node = posOperationObj.ledgerTreeNode;
                 if (!node) {
-                    toast('数据错误,请选择台账节点后再试', 'error');
+                    toastr.error('数据错误,请选择台账节点后再试');
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     return;
                 } else if (newText && newText !== '' && node.children && node.children.length > 0) {
-                    toast('父节点不可插入部位明细', 'error');
+                    toastr.error('父节点不可插入部位明细');
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     return;
                 } else if (newText && newText !== '' && (!node.b_code || node.b_code === '')) {
-                    toast('项目节不可插入部位明细', 'error');
+                    toastr.error('项目节不可插入部位明细');
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     return;
                 }
@@ -912,7 +1043,7 @@ $(document).ready(function() {
                 const data = {};
                 if (col.field === 'name') {
                     if (newText === '' && posData) {
-                        toast('部位名称不可为空', 'error', 'exclamation-circle');
+                        toastr.error('部位名称不可为空');
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                         return;
                     } else if (!posData) {
@@ -929,7 +1060,7 @@ $(document).ready(function() {
                         data.updateData = {id: posData.id, name: newText};
                     }
                 } else if (!posData) {
-                    toast('新增部位请先输入名称', 'warning');
+                    toastr.warning('新增部位请先输入名称');
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     return;
                 } else {
@@ -976,7 +1107,7 @@ $(document).ready(function() {
                         for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
                             const colSetting = sheet.zh_setting.cols[iCol];
                             if (colSetting.field === 'name') {
-                                toast('部位名称不能为空', 'error');
+                                toastr.error('部位名称不能为空');
                                 return;
                             }
                             const style = sheet.getStyle(iRow, iCol);
@@ -1040,12 +1171,12 @@ $(document).ready(function() {
         clipboardPasted: function (e, info) {
             const node = treeOperationObj.getSelectNode(ledgerSpread.getActiveSheet());
             if (node.code && (node.code !== '')) {
-                toast('项目节不可含有清单明细', 'error');
+                toastr.error('项目节不可含有清单明细');
                 posOperationObj.loadCurPosData();
                 return;
             }
             if (node.children && (node.children.length > 0)) {
-                toast('仅清单子项可以含有部位明细', 'error');
+                toastr.error('仅清单子项可以含有部位明细');
                 posOperationObj.loadCurPosData();
                 return;
             }
@@ -1055,7 +1186,7 @@ $(document).ready(function() {
                 const sortData = info.sheet.zh_data || [];
                 if (sortData.length === 0 || info.cellRange.row + info.cellRange.rowCount > sortData.length) {
                     if (info.cellRange.col !== 0) {
-                        toast('新增部位请先输入名称', 'warning');
+                        toastr.warning('新增部位请先输入名称');
                         posOperationObj.loadCurPosData();
                         return;
                     }
@@ -1309,7 +1440,7 @@ $(document).ready(function() {
                 if (!stdNode) { return; }
                 if (stdType === 'gcl') {
                     if (mainNode.code && mainNode.code !== '' && !mainTree.isLeafXmj(mainNode)) {
-                        toast('非最底层项目下,不应添加清单', 'warning');
+                        toastr.warning('非最底层项目下,不应添加清单');
                         return;
                     }
                 }
@@ -1372,7 +1503,7 @@ $(document).ready(function() {
                 if (!mainNode || !mainTree) { return; }
 
                 if (mainNode.code && mainNode.code !== '' && !mainTree.isLeafXmj(mainNode)) {
-                    toast('非最底层项目下,不应添加清单', 'error');
+                    toastr.error('非最底层项目下,不应添加清单');
                     return;
                 }
 
@@ -1642,7 +1773,7 @@ $(document).ready(function() {
                 $('p', resultDiv).text(data.company);
                 resultDiv.show();
             } else {
-                toast('未查询到该审核人', 'info');
+                toastr.info('未查询到该审核人');
                 resultDiv.hide();
             }
         }, () => {
@@ -1760,14 +1891,14 @@ $(document).ready(function() {
                         $(this).removeClass('border-primary');
                     })
                 } else {
-                    toast('选择的Excel无有效数据,请重新选择', 'hint');
+                    toastr.info('选择的Excel无有效数据,请重新选择');
                     $('#upload-ledger-sheets').hide();
                 }
                 $('#select-excel-loading').hide();
             });
         } catch(err) {
             $('#select-excel-loading').hide();
-            toast('加载excel异常,请刷新当前页面', 'error');
+            toastr.error('加载excel异常,请刷新当前页面');
             $('#upload-ledger-sheets').hide();
         }
     });
@@ -1828,7 +1959,7 @@ $(document).ready(function() {
 // 检查上报情况
 function checkAuditorFrom () {
     if ($('#auditors li').length === 0) {
-        toast('请先选择审批人,再上报数据', 'error', 'exclamation-circle');
+        toastr.error('请先选择审批人,再上报数据');
         return false;
     }
 }

+ 2 - 1
app/public/js/ledger_tree_col.js

@@ -42,7 +42,8 @@ const ledgerTreeCol = {
     initSpreadSetting(setting) {
         for (const col of setting.cols) {
             if (col.readOnly && Object.prototype.toString.apply(col.readOnly) === "[object String]") {
-                col.readOnly = this.getEvent(col.readOnly);
+                //col.readOnly = this.getEvent(col.readOnly);
+                delete col.readOnly;
             }
         }
     }

+ 48 - 2
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -659,6 +659,21 @@ const SpreadJsObj = {
         }
         return copyData.join('\n');
     },
+    analysisPasteText: function (text) {
+        const result = [];
+        if (text === '') return result;
+
+        const rows = text.split('\n');
+        for (const r of rows) {
+            const cols = r.split('\t');
+            result.push(cols);
+        }
+        return result;
+    },
+    analysisPasteHtml: function (html) {
+        const result = [];
+        if (!html || html === '') return result;
+    },
     /**
      * 树表结构,定位至指定的节点
      * @param {GC.Spread.Sheets.Worksheet} sheet - 需要定位的sheet
@@ -1609,5 +1624,36 @@ const SpreadJsObj = {
             combo.itemHeight(10).editorValueType(spreadNS.CellTypes.EditorValueType.value).items(items);
             return combo;
         },
-    }
-};
+    },
+
+    Clipboard: (function () {
+        let cText = '', cHtml;
+        const setCopyData = function (text, html) {
+            cText = text;
+            cHtml = html;
+        };
+        const getPasteData = function () {
+            return {text: cText, html: cHtml};
+        };
+        const clearData = function () {
+            cText = '';
+            cHtml = undefined;
+        };
+        const setSheetFilterCopyData = function (sheet) {
+            cText = SpreadJsObj.getFilterCopyText(sheet);
+            cHtml = SpreadJsObj.getFilterCopyHTML(sheet);
+        };
+        const getAnalysisPasteText = function () {
+            return SpreadJsObj.analysisPasteText(cText);
+        };
+        const getAnalysisPasteHtml = function () {
+            return SpreadJsObj.analysisPasteHtml(cHtml);
+        }
+        return {
+            setCopyData, getPasteData, clearData,
+            setSheetFilterCopyData,
+            getAnalysisPasteText, getAnalysisPasteHtml,
+        }
+    })(),
+};
+

+ 1 - 0
config/web.js

@@ -109,6 +109,7 @@ const JsFiles = {
                     "/public/js/js-xlsx/xlsx.utils.js",
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
                     "/public/js/decimal.min.js",
+                    "/public/js/toastr.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/sub_menu.js",