Quellcode durchsuchen

台账分解、台账修订、计量台账,新增表达式

MaiXinRong vor 5 Jahren
Ursprung
Commit
a2a6a35974

+ 166 - 15
app/public/js/ledger.js

@@ -22,6 +22,9 @@ const invalidFields = {
     posCode: ['b_code'],
     posCalc: ['sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp'],
 };
+function transExpr(expr) {
+    return expr.replace('=', '').replace('%', '/100');
+}
 
 $(document).ready(function() {
     autoFlashHeight();
@@ -72,6 +75,17 @@ $(document).ready(function() {
 
     // 定义事件
     const treeOperationObj = {
+        loadExprToInput(sheet) {
+            const sel = sheet.getSelections()[0];
+            const col = sheet.zh_setting.cols[sel.col], cell = sheet.getCell(sel.row, sel.col);
+            if (col.type === 'Number') {
+                const data = SpreadJsObj.getSelectObject(sheet);
+                $('#bills-expr').val(data[col.field]).attr('field', col.field).attr('org', data[col.field])
+                    .attr('readOnly', readOnly || cell.locked());
+            } else {
+                $('#bills-expr').val('').attr('readOnly', true);
+            }
+        },
         getSelectNode: function (sheet) {
             if (!sheet || !sheet.zh_tree) {
                 return null;
@@ -385,7 +399,18 @@ $(document).ready(function() {
                 }
                 // 获取更新数据
                 if (info.editingText) {
-                    data[col.field] = col.type === 'Number' ? parseFloat(info.editingText) : info.editingText.replace('\n', '');
+                    const num = _.toNumber(info.editingText);
+                    if (num) {
+                        data[col.field] = num;
+                    } else {
+                        try {
+                            data[col.field] = math.evaluate(transExpr(info.editingText));
+                        } catch(err) {
+                            toastr.error('输入的表达式非法');
+                            SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                            return;
+                        }
+                    }
                 } else {
                     data[col.field] = null;
                 }
@@ -444,6 +469,16 @@ $(document).ready(function() {
                                 if (num) {
                                     data[colSetting.field] = num;
                                     bPaste = true;
+                                } else {
+                                    try {
+                                        data[colSetting.field] = math.evaluate(transExpr(value));
+                                        bPaste = true;
+                                    } catch(err) {
+                                        if (!bHint) {
+                                            toastr.warning('输入的表达式非法');
+                                            bHint = true;
+                                        }
+                                    }
                                 }
                             } else {
                                 data[colSetting.field] = value;
@@ -520,7 +555,11 @@ $(document).ready(function() {
                             data[colSetting.field] = num;
                             bPaste = true;
                         } else {
-                            bNumHint = true;
+                            try {
+                                data[colSetting.field] = math.evaluate(transExpr(value));
+                            } catch(err) {
+                                bNumHint = true;
+                            }
                         }
                     } else {
                         data[colSetting.field] = value;
@@ -538,7 +577,7 @@ $(document).ready(function() {
             if (bGclHint) hint.push('工程量清单,不可粘贴设计数量');
             if (bQtyHint) hint.push('含有部位明细的清单,不可粘贴数量');
             if (bCodeHint) hint.push('含有部位明细的清单,清单编号不可粘贴空值');
-            if (bNumHint) 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('复制粘贴的数据中,存在非法数据,已过滤');
@@ -651,6 +690,7 @@ $(document).ready(function() {
                 posSearch.search($('#pos-keyword').val());
             }
             SpreadJsObj.saveTopAndSelect(info.sheet, ckBillsSpread);
+            treeOperationObj.loadExprToInput(info.sheet);
         },
         topRowChanged(e, info) {
             SpreadJsObj.saveTopAndSelect(info.sheet, ckBillsSpread);
@@ -782,6 +822,38 @@ $(document).ready(function() {
             });
         });
 
+        $('#bills-expr').bind('change mouseleave', function () {
+            const expr = $(this);
+            const sheet = ledgerSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(sheet);
+            const field = expr.attr('field'), orgValue = expr.attr('org'), newValue = expr.val();
+            if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
+
+            const data = {
+                id: select.id,
+                tender_id: select.tender_id,
+                ledger_id: select.ledger_id
+            };
+            const num = _.toNumber(newValue);
+            if (num) {
+                data[field] = num;
+            } else {
+                try {
+                    data[field] = math.evaluate(transExpr(newValue));
+                } catch (err) {
+                    toastr.error('输入的表达式非法');
+                    return;
+                }
+            }
+
+            // 更新至服务器
+            postData(window.location.pathname + '/update', {postType: 'update', postData: data}, function (result) {
+                const refreshNode = ledgerTree.loadPostData(result);
+                expr.val(select[field]);
+                treeOperationObj.refreshTree(sheet, refreshNode);
+            });
+        });
+
         let batchInsertObj;
         // 右键菜单
         $.contextMenu({
@@ -1037,7 +1109,23 @@ $(document).ready(function() {
                 } else {
                     data.updateType = 'update';
                     data.updateData = {id: posData.id};
-                    data.updateData[col.field] = col.type === 'Number' ? parseFloat(newText) : newText;
+
+                    if (col.type === 'Number') {
+                        const num = _.toNumber(newText);
+                        if (num) {
+                            data.updateData[col.field] = num;
+                        } else {
+                            try {
+                                data.updateData[col.field] = math.evaluate(transExpr(newText));
+                            } catch(err) {
+                                toastr.error('输入的表达式非法');
+                                SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                                return;
+                            }
+                        }
+                    } else {
+                        data.updateData[col.field] = newText;
+                    }
                 }
                 postData('/tender/' + getTenderId() + '/pos/update', data, function (result) {
                     const updateRst = pos.updateDatas(result.pos);
@@ -1164,32 +1252,94 @@ $(document).ready(function() {
                 }
                 const lastOrder = sortData.length > 0 ? sortData[sortData.length - 1].porder + 1 : 1;
                 for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                    let bPaste = false;
                     const curRow = info.cellRange.row + iRow;
                     const posData = curRow >= sortData.length ? {lid: node.id, porder: lastOrder + curRow - sortData.length} : {id: sortData[curRow].id, lid: node.id};
                     for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
                         const curCol = info.cellRange.col + iCol;
                         const colSetting = info.sheet.zh_setting.cols[curCol];
                         posData[colSetting.field] = info.sheet.getText(curRow, curCol);
+
                         if (colSetting.type === 'Number') {
-                            posData[colSetting.field] = _.toNumber(posData[colSetting.field]);
+                            const num = _.toNumber(posData[colSetting.field]);
+                            if (num) {
+                                posData[colSetting.field] = num;
+                                bPaste = true;
+                            } else {
+                                try {
+                                    posData[colSetting.field] = math.evaluate(transExpr(posData[colSetting.field]));
+                                    bPaste = true;
+                                } catch(err) {
+                                    toastr.warning('粘贴了表达式非法,已过滤');
+                                }
+                            }
                         }
                     }
-                    data.push(posData);
+                    if (bPaste) {
+                        data.push(posData);
+                    }
                 }
-                postData('/tender/' + getTenderId() + '/pos/paste', data, function (result) {
-                    pos.updateDatas(result.pos);
-                    posOperationObj.loadCurPosData();
-                    const loadResult = ledgerTree.loadPostData(result.ledger);
-                    treeOperationObj.refreshTree(ledgerSpread.getActiveSheet(), loadResult);
-                    posOperationObj.loadCurPosData();
-                    treeOperationObj.refreshOperationValid(ledgerSpread.getActiveSheet());
-                }, function () {
+                if (data.length > 0) {
+                    postData('/tender/' + getTenderId() + '/pos/paste', data, function (result) {
+                        pos.updateDatas(result.pos);
+                        posOperationObj.loadCurPosData();
+                        const loadResult = ledgerTree.loadPostData(result.ledger);
+                        treeOperationObj.refreshTree(ledgerSpread.getActiveSheet(), loadResult);
+                        posOperationObj.loadCurPosData();
+                        treeOperationObj.refreshOperationValid(ledgerSpread.getActiveSheet());
+                    }, function () {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                    });
+                } else {
                     SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-                });
+                }
+            }
+        },
+        selectionChanged: function (e, info) {
+            const col = info.sheet.zh_setting.cols[info.newSelections[0].col];
+            const cell = info.sheet.getCell(info.newSelections[0].row, info.newSelections[0].col);
+            if (col.type === 'Number') {
+                const data = SpreadJsObj.getSelectObject(info.sheet);
+                $('#pos-expr').val(data[col.field]).attr('field', col.field).attr('org', data[col.field])
+                    .attr('row', info.newSelections[0].row).attr('readOnly', readOnly || cell.locked());
+            } else {
+                $('#pos-expr').val('').attr('readOnly', true);
             }
         },
     };
+    posSpread.bind(spreadNS.Events.SelectionChanged, posOperationObj.selectionChanged)
     if (!posSpreadSetting.readOnly) {
+        $('#pos-expr').bind('change mouseleave', function () {
+            const expr = $(this);
+            const posSheet = posSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(posSheet);
+            const field = expr.attr('field'), orgValue = expr.attr('org'), newValue = expr.val(), row = expr.attr('row');
+            if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
+
+            const data = {id: select.id};
+            const num = _.toNumber(newValue);
+            if (num) {
+                data[field] = num;
+            } else {
+                try {
+                    data[field] = math.evaluate(transExpr(newValue));
+                } catch (err) {
+                    toastr.error('输入的表达式非法');
+                    return;
+                }
+            }
+
+            // 更新至服务器
+            postData('/tender/' + getTenderId() + '/pos/update', {updateType: 'update', updateData: data}, function (result) {
+                const updateRst = pos.updateDatas(result.pos);
+                expr.val(select[field]);
+                SpreadJsObj.reLoadRowData(posSheet, _.toNumber(row));
+                const loadResult = ledgerTree.loadPostData(result.ledger);
+                treeOperationObj.refreshTree(ledgerSpread.getActiveSheet(), loadResult);
+                treeOperationObj.refreshOperationValid(ledgerSpread.getActiveSheet());
+            });
+        });
+
         SpreadJsObj.addDeleteBind(posSpread, posOperationObj.deletePress);
         posSpread.bind(spreadNS.Events.EditStarting, posOperationObj.editStarting);
         posSpread.bind(spreadNS.Events.EditEnded, posOperationObj.editEnded);
@@ -1235,6 +1385,7 @@ $(document).ready(function() {
         SpreadJsObj.resetTopAndSelect(posSpread.getActiveSheet());
 
         treeOperationObj.refreshOperationValid(ledgerSpread.getActiveSheet());
+        treeOperationObj.loadExprToInput(ledgerSpread.getActiveSheet());
     }, null, true);
 
     let stdXmj, stdGcl, dealBills, searchLedger;

+ 163 - 5
app/public/js/revise.js

@@ -9,6 +9,9 @@
  */
 
 const ckBillsSpread = window.location.pathname + '-billsSelect';
+function transExpr(expr) {
+    return expr.replace('=', '').replace('%', '/100');
+}
 
 $(document).ready(() => {
     autoFlashHeight();
@@ -66,6 +69,17 @@ $(document).ready(() => {
     pos.loadDatas(posData);
 
     const billsTreeSpreadObj = {
+        loadExprToInput(sheet) {
+            const sel = sheet.getSelections()[0];
+            const col = sheet.zh_setting.cols[sel.col], cell = sheet.getCell(sel.row, sel.col);
+            if (col.type === 'Number') {
+                const data = SpreadJsObj.getSelectObject(sheet);
+                $('#bills-expr').val(data[col.field]).attr('field', col.field).attr('org', data[col.field])
+                    .attr('readOnly', readOnly || cell.locked());
+            } else {
+                $('#bills-expr').val('').attr('readOnly', true);
+            }
+        },
         getDefaultSelectInfo: function (sheet) {
             const tree = sheet.zh_tree;
             if (!tree) return;
@@ -196,6 +210,7 @@ $(document).ready(() => {
                 SpreadJsObj.saveTopAndSelect(billsSheet, ckBillsSpread);
                 posSearch.search($('#pos-keyword').val());
             }
+            billsTreeSpreadObj.loadExprToInput(info.sheet);
         },
         /**
          * 新增节点
@@ -318,7 +333,23 @@ $(document).ready(() => {
                 }
                 // 获取更新数据
                 if (info.editingText) {
-                    data[col.field] = col.type === 'Number' ? parseFloat(info.editingText) : info.editingText.replace('\n', '');
+                    const text = info.editingText.replace('\n', '');
+                    if (col.type === 'Number') {
+                        const num = _.toNumber(text);
+                        if (num) {
+                            data[col.field] = num;
+                        } else {
+                            try {
+                                data[col.field] = math.evaluate(transExpr(text));
+                            } catch(err) {
+                                toastr.error('输入的表达式非法');
+                                SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                                return;
+                            }
+                        }
+                    } else {
+                        data[col.field] = text;
+                    }
                 } else {
                     data[col.field] = null;
                 }
@@ -379,7 +410,24 @@ $(document).ready(() => {
                                 continue;
                             }
                         }
-                        data[colSetting.field] = value;
+                        if (colSetting.type === 'Number') {
+                            const num = _.toNumber(value);
+                            if (num) {
+                                data[colSetting.field] = num;
+                            } else {
+                                try {
+                                    data[colSetting.field] = math.evaluate(transExpr(value));
+                                } catch (err) {
+                                    if (!bHint) {
+                                        toastr.warning('粘贴的表达式非法,已过滤');
+                                        bHint = true;
+                                    }
+                                    continue;
+                                }
+                            }
+                        } else {
+                            data[colSetting.field] = value;
+                        }
                         bPaste = true;
                     }
                     if (bPaste) {
@@ -451,6 +499,7 @@ $(document).ready(() => {
         },
     };
     billsTreeSpreadObj.refreshOperationValid(billsSheet);
+    billsTreeSpreadObj.loadExprToInput(info.sheet);
     billsSpread.bind(spreadNS.Events.SelectionChanged, billsTreeSpreadObj.selectionChanged);
     billsSpread.bind(spreadNS.Events.topRowChanged, billsTreeSpreadObj.topRowChanged);
     if (!readOnly) {
@@ -458,6 +507,38 @@ $(document).ready(() => {
         $('a[name="base-opr"]').click(function () {
             billsTreeSpreadObj.baseOpr(billsSheet, this.getAttribute('type'));
         });
+
+        $('#bills-expr').bind('change mouseleave', function () {
+            const expr = $(this);
+            const select = SpreadJsObj.getSelectObject(billsSheet);
+            const field = expr.attr('field'), orgValue = expr.attr('org'), newValue = expr.val();
+            if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
+
+            const data = {
+                id: select.id,
+                tender_id: select.tender_id,
+                ledger_id: select.ledger_id
+            };
+            const num = _.toNumber(newValue);
+            if (num) {
+                data[field] = num;
+            } else {
+                try {
+                    data[field] = math.evaluate(transExpr(newValue));
+                } catch (err) {
+                    toastr.error('输入的表达式非法');
+                    return;
+                }
+            }
+
+            // 更新至服务器
+            postData(window.location.pathname + '/update', {postType: 'update', postData: data}, function (result) {
+                const refreshNode = billsTree.loadPostData(result);
+                expr.val(select[field]);
+                billsTreeSpreadObj.refreshTree(info.sheet, refreshNode);
+            });
+        });
+
         billsSpread.bind(spreadNS.Events.EditEnded, billsTreeSpreadObj.editEnded);
         billsSpread.bind(spreadNS.Events.ClipboardPasting, billsTreeSpreadObj.clipboardPasting);
         billsSpread.bind(spreadNS.Events.ClipboardPasted, billsTreeSpreadObj.clipboardPasted);
@@ -581,7 +662,22 @@ $(document).ready(() => {
             } else {
                 data.posPostType = 'update';
                 data.postData = {id: posData.id};
-                data.postData[col.field] = col.type === 'Number' ? parseFloat(newText) : newText;
+                if (col.type === 'Number') {
+                    const num = _.toNumber(newText);
+                    if (num) {
+                        data.postData[col.field] = num;
+                    } else {
+                        try {
+                            data.postData[col.field] = math.evaluate(transExpr(newText));
+                        } catch(err) {
+                            toastr.error('输入的表达式非法');
+                            SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                            return;
+                        }
+                    }
+                } else {
+                    data.postData[col.field] = newText;
+                }
             }
             postData(window.location.pathname + '/update', data, function (result) {
                 const updateRst = pos.updateDatas(result.pos);
@@ -723,8 +819,10 @@ $(document).ready(() => {
                     return;
                 }
             }
+            let bHint = false;
             const lastOrder = sortData.length > 0 ? sortData[sortData.length - 1].porder + 1 : 1;
             for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                let bPaste = true;
                 const curRow = info.cellRange.row + iRow;
                 const posData = curRow >= sortData.length ? {lid: node.id, porder: lastOrder + curRow - sortData.length} : {id: sortData[curRow].id, lid: node.id};
                 for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
@@ -732,10 +830,29 @@ $(document).ready(() => {
                     const colSetting = info.sheet.zh_setting.cols[curCol];
                     posData[colSetting.field] = info.sheet.getText(curRow, curCol);
                     if (colSetting.type === 'Number') {
-                        posData[colSetting.field] = _.toNumber(posData[colSetting.field]);
+                        const num = _.toNumber(posData[colSetting.field]);
+                        if (num) {
+                            posData[colSetting.field] = num;
+                        } else {
+                            try {
+                                posData[colSetting.field] = math.evaluate(transExpr(posData[colSetting.field]));
+                            } catch (err) {
+                                if (!bHint) {
+                                    toastr.warning('粘贴了非法表达式,已过滤');
+                                    bHint = true;
+                                }
+                                bPaste = false;
+                            }
+                        }
                     }
                 }
-                data.push(posData);
+                if (bPaste) {
+                    data.push(posData);
+                }
+            }
+            if (data.length === 0) {
+                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                return;
             }
             postData(window.location.pathname + '/update', {postType: 'pos', posPostType: 'paste', postData: data}, function (result) {
                 pos.updateDatas(result.pos);
@@ -748,10 +865,51 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
             });
         },
+        selectionChanged: function (e, info) {
+            const col = info.sheet.zh_setting.cols[info.newSelections[0].col];
+            const cell = info.sheet.getCell(info.newSelections[0].col, info.newSelections[0].col);
+            if (col.type === 'Number') {
+                const data = SpreadJsObj.getSelectObject(info.sheet);
+                $('#pos-expr').val(data[col.field]).attr('field', col.field).attr('org', data[col.field])
+                    .attr('row', info.newSelections[0].row).attr('readOnly', readOnly || cell.locked());
+            }
+        },
     };
     posSpreadObj.loadCurPosData();
     SpreadJsObj.resetTopAndSelect(posSheet);
+    posSpread.bind(spreadNS.Events.SelectionChanged, posSpreadObj.selectionChanged);
     if (!readOnly) {
+        $('#pos-expr').bind('change mouseleave', function () {
+            const expr = $(this);
+            const select = SpreadJsObj.getSelectObject(posSheet);
+            const field = expr.attr('field'), orgValue = expr.attr('org'), newValue = expr.val();
+            if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
+
+            const data = {id: select.id};
+            const num = _.toNumber(newValue);
+            if (num) {
+                data[field] = num;
+            } else {
+                try {
+                    data[field] = math.evaluate(transExpr(newValue));
+                } catch (err) {
+                    toastr.error('输入的表达式非法');
+                    return;
+                }
+            }
+
+            // 更新至服务器
+            postData(window.location.pathname + '/update', {posPostType: 'update', posData: data}, function (result) {
+                const updateRst = pos.updateDatas(result.pos);
+                expr.val(select[field]);
+                // 刷新当前行, 不适用于新增(在非下一空白行新增)
+                SpreadJsObj.reLoadRowData(info.sheet, _.toNumber(row));
+                const loadResult = billsTree.loadPostData(result.ledger);
+                billsTreeSpreadObj.refreshTree(billsSheet, loadResult);
+                billsTreeSpreadObj.refreshOperationValid(billsSheet);
+            });
+        });
+
         posSpread.bind(spreadNS.Events.EditStarting, posSpreadObj.editStarting);
         posSpread.bind(spreadNS.Events.EditEnded, posSpreadObj.editEnded);
         posSpread.bind(spreadNS.Events.ClipboardPasting, posSpreadObj.clipboardPasting);

+ 206 - 11
app/public/js/stage.js

@@ -12,6 +12,10 @@ function checkTzMeasureType () {
     return tender.measure_type === measureType.tz.value;
 }
 
+function transExpr(expr) {
+    return expr.replace('=', '').replace('%', '/100');
+}
+
 /**
  * 从cookie中读取缓存的列显示设置,没有则取默认
  * @returns {*[]}
@@ -481,6 +485,22 @@ $(document).ready(() => {
     SpreadJsObj.initSheet(spSpread.getActiveSheet(), posSpreadSetting);
 
     const stageTreeSpreadObj = {
+        loadExprToInput(sheet) {
+            const sel = sheet.getSelections()[0];
+            const col = sheet.zh_setting.cols[sel.col], cell = sheet.getCell(sel.row, sel.col);
+            if (col.type === 'Number') {
+                const data = SpreadJsObj.getSelectObject(sheet);
+                const nodePos = stagePos.getLedgerPos(data.id);
+                if (nodePos && nodePos.length > 0) {
+                    $('#bills-expr').val('').attr('readOnly', true);
+                } else {
+                    $('#bills-expr').val(data[col.field]).attr('field', col.field).attr('org', data[col.field])
+                        .attr('readOnly', readOnly || cell.locked());
+                }
+            } else {
+                $('#bills-expr').val('').attr('readOnly', true);
+            }
+        },
         refreshTreeNodes: function (sheet, nodes) {
             const tree = sheet.zh_tree;
             if (!tree) { return }
@@ -497,7 +517,22 @@ $(document).ready(() => {
                 const node = sortData[info.row], updateData = {};
 
                 const orgValue = node[col.field];
-                const newValue =  col.type === 'Number' ? parseFloat(info.editingText) : info.editingText;
+                let newValue = info.editingText;
+
+                if (col.type === 'Number') {
+                    const num = _.toNumber(newValue);
+                    if (num) {
+                        newValue = num;
+                    } else {
+                        try {
+                            newValue = math.evaluate(transExpr(newValue));
+                        } catch(err) {
+                            toastr.error('输入的表达式非法');
+                            SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                            return;
+                        }
+                    }
+                }
                 if (orgValue == newValue || ((!orgValue || orgValue === '') && (newValue === ''))) {
                     return;
                 }
@@ -548,6 +583,7 @@ $(document).ready(() => {
                 posSearch.search();
             }
             SpreadJsObj.saveTopAndSelect(info.sheet, ckBillsSpread);
+            stageTreeSpreadObj.loadExprToInput(info.sheet);
         },
         deletePress(sheet) {
             if (sheet.zh_setting && sheet.zh_dataType === 'tree') {
@@ -625,13 +661,14 @@ $(document).ready(() => {
             if (info.sheet.zh_setting && info.sheet.zh_tree) {
                 const sheet = info.sheet, setting = info.sheet.zh_setting;
                 const filterNodes = [], datas = [], dgnDatas = [];
+                let bHint = false;
 
                 for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
                     const curRow = iRow + info.cellRange.row;
                     const node = sheet.zh_tree.getItemsByIndex(curRow);
 
                     const data = {lid: node.id}, dgnData = {id: node.id};
-                    let filter = true, filterDgn = true;
+                    let filter = false, filterDgn = false;
                     for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
                         const curCol = info.cellRange.col + iCol;
                         const col = info.sheet.zh_setting.cols[curCol];
@@ -644,12 +681,41 @@ $(document).ready(() => {
                             if (nodePos && nodePos.length > 0) continue;
                         }
 
+                        const text = sheet.getText(curRow, curCol);
                         if (setting.dgnUpFields.indexOf(col.field) !== -1) {
-                            dgnData[col.field] = _.toNumber(sheet.getText(curRow, curCol));
-                            filterDgn = false;
+                            const num = _.toNumber(text);
+                            if (num) {
+                                dgnData[col.field] = num;
+                            } else {
+                                try {
+                                    dgnData[col.field] = math.evaluate(transExpr(text));
+                                } catch(err) {
+                                    if (!bHint) {
+                                        toastr.warning('粘贴了非法表达式,已过滤');
+                                        bHint = true;
+                                    }
+                                    filterDgn = true;
+                                }
+                            }
                         } else {
-                            data[col.field] = col.type === 'Number' ? _.toNumber(sheet.getText(curRow, curCol)) : sheet.getText(curRow, curCol);
-                            filter = false;
+                            if (col.type === 'Number') {
+                                const num = _.toNumber(text);
+                                if (num) {
+                                    data[col.field] = num;
+                                } else {
+                                    try {
+                                        data[col.field] = math.evaluate(transExpr(text));
+                                    } catch(err) {
+                                        if (!bHint) {
+                                            toastr.warning('粘贴了非法表达式,已过滤');
+                                            bHint = true;
+                                        }
+                                        filter = true;
+                                    }
+                                }
+                            } else {
+                                data[col.field] = text;
+                            }
                         }
                     }
                     if (filter && filterDgn) {
@@ -837,8 +903,61 @@ $(document).ready(() => {
             },
         }
     });
+    if (!readOnly) {
+        $('#bills-expr').bind('change mouseleave', function () {
+            const expr = $(this);
+            const sheet = slSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(sheet);
+            const field = expr.attr('field'), orgValue = expr.attr('org'), updateData = {};
+            let newValue = expr.val();
+
+            const num = _.toNumber(newValue);
+            if (num) {
+                newValue = num;
+            } else {
+                try {
+                    newValue = math.evaluate(transExpr(newValue));
+                } catch(err) {
+                    toastr.error('输入的表达式非法');
+                    return;
+                }
+            }
+            if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
+
+            if (field.indexOf('_dgn_') > 0) {
+                updateData.dgn = {
+                    id: select.id
+                };
+                updateData.dgn[field] = newValue;
+            } else {
+                updateData.stage = {
+                    lid: select.id
+                };
+                updateData.stage[field] = newValue;
+            }
+
+            // 更新至服务器
+            postData(window.location.pathname + '/update', {bills: updateData}, function (result) {
+                const nodes = stageTree.loadPostStageData(result);
+                expr.val(select[field]);
+                stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), nodes);
+            });
+        });
+    }
+    stageTreeSpreadObj.loadExprToInput(slSpread.getActiveSheet());
 
     const stagePosSpreadObj = {
+        loadExprToInput(sheet) {
+            const sel = sheet.getSelections()[0];
+            const col = sheet.zh_setting.cols[sel.col], cell = sheet.getCell(sel.row, sel.col);
+            if (col.type === 'Number') {
+                const data = SpreadJsObj.getSelectObject(sheet);
+                $('#pos-expr').val(data[col.field]).attr('field', col.field).attr('org', data[col.field])
+                    .attr('row', sel.row).attr('readOnly', readOnly || cell.locked());
+            } else {
+                $('#pos-expr').val('').attr('readOnly', true);
+            }
+        },
         /**
          * 加载部位明细 根据当前台账选择节点
          */
@@ -913,7 +1032,22 @@ $(document).ready(() => {
                 } else {
                     data.updateType = 'update';
                     data.updateData = {pid: posData.id, lid: posData.lid};
-                    data.updateData[col.field] = col.type === 'Number' ? parseFloat(info.editingText) : info.editingText;
+                    if (col.type === 'Number') {
+                        const num = _.toNumber(info.editingText);
+                        if (num) {
+                            data.updateData[col.field] = num;
+                        } else {
+                            try {
+                                data.updateData[col.field] = math.evaluate(transExpr(info.editingText));
+                            } catch(err) {
+                                toastr.error('输入的表达式非法');
+                                SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                                return;
+                            }
+                        }
+                    } else {
+                        data.updateData[col.field] = info.editingText;
+                    }
                 }
                 // 提交数据到服务器
                 postData(window.location.pathname + '/update', {pos: data}, function (result) {
@@ -982,8 +1116,20 @@ $(document).ready(() => {
                             const curCol = info.cellRange.col + iCol;
                             const colSetting = info.sheet.zh_setting.cols[curCol];
                             newData[colSetting.field] = info.sheet.getText(curRow, curCol);
-                            if (colSetting.type === 'Number') {
-                                newData[colSetting.field] = _.toNumber(newData[colSetting.field]);
+                            if (col.type === 'Number') {
+                                const num = _.toNumber(newData[colSetting.field]);
+                                if (num) {
+                                    newData[colSetting.field] = num;
+                                } else {
+                                    try {
+                                        newData[colSetting.field] = math.evaluate(transExpr(newData[colSetting.field]));
+                                    } catch(err) {
+                                        toastr.error('输入的表达式非法');
+                                        self.loadCurPosData();
+                                        return;
+
+                                    }
+                                }
                             }
                         }
                         data.updateData.push(newData);
@@ -999,8 +1145,19 @@ $(document).ready(() => {
                                 const curCol = info.cellRange.col + iCol;
                                 const colSetting = info.sheet.zh_setting.cols[curCol];
                                 newData[colSetting.field] = info.sheet.getText(curRow, curCol);
-                                if (colSetting.type === 'Number') {
-                                    newData[colSetting.field] = _.toNumber(newData[colSetting.field]);
+                                if (col.type === 'Number') {
+                                    const num = _.toNumber(newData[colSetting.field]);
+                                    if (num) {
+                                        newData[colSetting.field] = num;
+                                    } else {
+                                        try {
+                                            newData[colSetting.field] = math.evaluate(transExpr(newData[colSetting.field]));
+                                        } catch(err) {
+                                            toastr.error('输入的表达式非法');
+                                            self.loadCurPosData();
+                                            return;
+                                        }
+                                    }
                                 }
                             }
                             data.updateData.push(newData);
@@ -1090,6 +1247,9 @@ $(document).ready(() => {
                 }
             }
         },
+        selectionChanged: function (e, info) {
+            stagePosSpreadObj.loadExprToInput(info.sheet);
+        }
     };
     // 加载上下窗口resizer
     $.divResizer({
@@ -1116,7 +1276,42 @@ $(document).ready(() => {
     spSpread.bind(spreadNS.Events.ClipboardPasting, stagePosSpreadObj.clipboardPasting);
     spSpread.bind(spreadNS.Events.ClipboardPasted, stagePosSpreadObj.clipboardPasted);
     spSpread.bind(spreadNS.Events.EditStarting, stagePosSpreadObj.editStarting);
+    spSpread.bind(spreadNS.Events.SelectionChanged, stagePosSpreadObj.selectionChanged);
     SpreadJsObj.addDeleteBind(spSpread, stagePosSpreadObj.deletePress);
+    if (!readOnly) {
+        $('#pos-expr').bind('change mouseleave', function () {
+            const expr = $(this);
+            const posSheet = spSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(posSheet);
+            const field = expr.attr('field'), orgValue = expr.attr('org'), newValue = expr.val(), row = expr.attr('row');
+            if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
+
+            const data = {pid: select.id, lid: select.lid};
+            const num = _.toNumber(newValue);
+            if (num) {
+                data[field] = num;
+            } else {
+                try {
+                    data[field] = math.evaluate(transExpr(newValue));
+                } catch (err) {
+                    toastr.error('输入的表达式非法');
+                    return;
+                }
+            }
+
+            // 提交数据到服务器
+            postData(window.location.pathname + '/update', {pos: {updateType: 'update', updateData: data}}, function (result) {
+                if (result.pos) {
+                    stagePos.updateDatas(result.pos.pos);
+                    stagePos.loadCurStageData(result.pos.curStageData);
+                    expr.val(select[field]);
+                    SpreadJsObj.reLoadRowData(posSheet, _.toNumber(row));
+                }
+                const refreshData = stageTree.loadPostStageData(result.ledger);
+                stageTreeSpreadObj.refreshTreeNodes(slSpread.getActiveSheet(), refreshData);
+            });
+        });
+    }
     if (!checkTzMeasureType()) {
         $.contextMenu({
             selector: '#stage-pos',

+ 2 - 2
app/public/js/stage_pay.js

@@ -69,12 +69,12 @@ $(document).ready(() => {
                 const percent = formula.match(this.percentReg);
                 if (percent) {
                     for (const p of percent) {
-                        const v = math.eval(p.replace('%', '/100'));
+                        const v = math.evaluate(p.replace('%', '/100'));
                         formula = formula.replace(p, v);
                     }
                 }
                 try {
-                    const value = math.eval(formula);
+                    const value = math.evaluate(formula);
                     return value;
                 } catch(err) {
                     return 0;

+ 11 - 1
app/view/ledger/explode.ejs

@@ -36,7 +36,7 @@
                         <div class="input-group-prepend">
                             <span class="input-group-text" id="basic-addon1">表达式</span>
                         </div>
-                        <input type="text" class="form-control m-0">
+                        <input type="text" class="form-control m-0" id="bills-expr" readonly="">
                     </div>
                 </div>
             </div>
@@ -76,6 +76,16 @@
                             </li>
                             <li class="nav-item" id="pos-search">
                             </li>
+                            <li class="nav-item">
+                                <div class="d-inline-block">
+                                    <div class="input-group input-group-sm ml-2 mt-1">
+                                        <div class="input-group-prepend">
+                                            <span class="input-group-text" id="basic-addon1">表达式</span>
+                                        </div>
+                                        <input type="text" class="form-control m-0" id="pos-expr" readonly="">
+                                    </div>
+                                </div>
+                            </li>
                         </ul>
                     </div>
                     <div class="sp-wrap" id="pos-spread">

+ 11 - 1
app/view/revise/info.ejs

@@ -38,7 +38,7 @@
                         <div class="input-group-prepend">
                             <span class="input-group-text" id="basic-addon1">表达式</span>
                         </div>
-                        <input type="text" class="form-control m-0">
+                        <input type="text" class="form-control m-0" id="bills-expr" readonly="">
                     </div>
                 </div>
             </div>
@@ -84,6 +84,16 @@
                             </li>
                             <li class="nav-item" id="pos-search">
                             </li>
+                            <li class="nav-item">
+                                <div class="d-inline-block">
+                                    <div class="input-group input-group-sm ml-2 mt-1">
+                                        <div class="input-group-prepend">
+                                            <span class="input-group-text" id="basic-addon1">表达式</span>
+                                        </div>
+                                        <input type="text" class="form-control m-0" id="pos-expr" readonly="">
+                                    </div>
+                                </div>
+                            </li>
                         </ul>
                     </div>
                     <div class="sp-wrap" id="pos-spread">

+ 12 - 1
app/view/stage/index.ejs

@@ -29,7 +29,7 @@
                         <div class="input-group-prepend">
                             <span class="input-group-text" id="basic-addon1">表达式</span>
                         </div>
-                        <input type="text" class="form-control m-0" <% if (stage.readOnly) { %> readonly="" <% } %>>
+                        <input type="text" class="form-control m-0" id="bills-expr" readonly="">
                     </div>
                 </div>
             </div>
@@ -83,6 +83,17 @@
                                     </div>
                                 </div>
                             </li>
+
+                            <li class="nav-item">
+                                <div class="d-inline-block">
+                                    <div class="input-group input-group-sm ml-2 mt-1">
+                                        <div class="input-group-prepend">
+                                            <span class="input-group-text" id="basic-addon1">表达式</span>
+                                        </div>
+                                        <input type="text" class="form-control m-0" id="pos-expr" readonly="">
+                                    </div>
+                                </div>
+                            </li>
                         </ul>
                     </div>
                     <div class="sp-wrap" id="stage-pos">

+ 3 - 0
config/web.js

@@ -110,6 +110,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/math.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/sub_menu.js",
@@ -161,6 +162,7 @@ const JsFiles = {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
                     "/public/js/decimal.min.js",
+                    "/public/js/math.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/sub_menu.js",
@@ -196,6 +198,7 @@ const JsFiles = {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
                     "/public/js/decimal.min.js",
+                    "/public/js/math.min.js",
                 ],
                 mergeFiles: [
                     "/public/js/sub_menu.js",