Преглед изворни кода

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

TonyKang пре 5 година
родитељ
комит
4948915927

+ 147 - 0
app/base/base_bills_service.js

@@ -17,6 +17,7 @@ const upFields = ['unit_price'];
 const qtyFields = ['sgfh_qty', 'sjcl_qty', 'qtcl_qty', 'quantity', 'deal_qty', 'dgn_qty1', 'dgn_qty2'];
 const tpFields = ['sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price', 'deal_tp'];
 const measureType = require('../const/tender').measureType;
+const math = require('mathjs');
 
 class BaseBillsSerivce extends TreeService {
 
@@ -517,6 +518,152 @@ class BaseBillsSerivce extends TreeService {
         const sqlParam = [tid];
         await this.db.query(sql, sqlParam);
     }
+
+    _calcExpr(data, field, expr, defaultValue, precision) {
+        if (expr) {
+            try {
+                data[field] = this.ctx.helper.round(math(expr), precision.value);
+            } catch (err) {
+            }
+        } else {
+            data[field] = this.ctx.helper.round(defaultValue, precision.value);
+        }
+    }
+
+    async pasteBlockData (tid, sid, pasteData, defaultData) {
+        if ((tid <= 0) || (sid <= 0)) return [];
+
+        if (!pasteData || pasteData.length <= 0) throw '复制数据错误';
+        for (const pd of pasteData) {
+            if (!pd || pd.length <= 0) throw '复制数据错误';
+            pd.sort(function (x, y) {
+                return x.level - y.level
+            });
+            if (pd[0].ledger_pid !== pasteData[0][0].ledger_pid) throw '复制数据错误:仅可操作同层节点';
+        }
+
+        const selectData = await this.getDataByKid(tid, sid);
+        if (!selectData) throw '粘贴数据错误';
+        const newParentPath = selectData.full_path.replace(selectData.ledger_id, '');
+
+        const pasteBillsData = [], pastePosData = [], leafBillsId = [];
+        const tpDecimal = this.ctx.tender.info.decimal.tp;
+        let maxId = await this._getMaxLid(this.ctx.tender.id);
+        for (const [i, pd] of pasteData.entries()) {
+            for (const d of pd) {
+                d.children = pd.filter(function (x) {
+                    return x.ledger_pid === d.ledger_id;
+                });
+            }
+            const pbd = [];
+            for (const [j, d] of pd.entries()) {
+                const newBills = {
+                    id: this.uuid.v4(),
+                    tender_id: tid,
+                    ledger_id: maxId + j + 1,
+                    ledger_pid: j === 0 ? selectData.ledger_pid : d.ledger_pid,
+                    level: d.level + selectData.level - pd[0].level,
+                    order: j === 0 ? selectData.order + i + 1 : d.order,
+                    is_leaf: d.is_leaf,
+                    code: d.code,
+                    b_code: d.b_code,
+                    name: d.name,
+                    unit: d.unit,
+                    unit_price: this.ctx.helper.round(d.unit_price, this.ctx.tender.info.decimal.up),
+                    source: d.source,
+                    remark: d.remark,
+                    drawing_code: d.drawaing_code,
+                    memo: d.memo,
+                    node_type: d.node_type,
+                    sgfh_expr: d.sgfh_expr,
+                    sjcl_expr: d.sjcl_expr,
+                    qtcl_expr: d.qtcl_expr,
+                };
+                for (const c of d.children) {
+                    c.ledger_pid = newBills.ledger_id;
+                }
+                const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, newBills.unit);
+                if (d.pos && d.pos.length > 0) {
+                    for (const pos of d.pos) {
+                        const newPos = {
+                            id: this.uuid.v4(),
+                            tid: tid,
+                            lid: newBills.id,
+                            name: pos.name,
+                            drawing_code: pos.drawing_code,
+                            add_user: this.ctx.session.sessionUser.accountId,
+                            in_time: new Date(),
+                            porder: pos.porder,
+                            position: pos.position,
+                            sgfh_expr: pos.sgfh_expr,
+                            sjcl_expr: pos.sjcl_expr,
+                            qtcl_expr: pos.qtcl_expr,
+                            add_stage: 0,
+                            add_times: 0,
+                        };
+                        this._calcExpr(newPos, 'sgfh_qty', pos.sgfh_expr, pos.sgfh_qty, precision);
+                        this._calcExpr(newPos, 'sjcl_qty', pos.sjcl_expr, pos.sjcl_qty, precision);
+                        this._calcExpr(newPos, 'qtcl_qty', pos.qtcl_expr, pos.qtcl_qty, precision);
+                        newPos.quantity = this.ctx.helper.add(newPos.sgfh_qty,
+                            this.ctx.helper.add(newPos.sjcl_qty, newPos.qtcl_qty));
+                        newBills.sgfh_qty = this.ctx.helper.add(newBills.sgfh_qty, pos.sgfh_qty);
+                        newBills.sjcl_qty = this.ctx.helper.add(newBills.sjcl_qty, pos.sjcl_qty);
+                        newBills.qtcl_qty = this.ctx.helper.add(newBills.qtcl_qty, pos.qtcl_qty);
+                        if (defaultData) this.ctx.helper._.assignIn(newPos, defaultData);
+                        pastePosData.push(newPos);
+                    }
+                } else {
+                    this._calcExpr(newBills, 'sgfh_qty', newBills.sgfh_expr, d.sgfh_qty, precision);
+                    this._calcExpr(newBills, 'sjcl_qty', newBills.sjcl_expr, d.sjcl_qty, precision);
+                    this._calcExpr(newBills, 'qtcl_qty', newBills.qtcl_expr, d.qtcl_qty, precision);
+                }
+                newBills.quantity = this.ctx.helper.add(newBills.sgfh_qty,
+                    this.ctx.helper.add(newBills.sjcl_qty, newBills.qtcl_qty));
+                newBills.sgfh_tp = this.ctx.helper.mul(newBills.sgfh_qty, newBills.unit_price, tpDecimal);
+                newBills.sjcl_tp = this.ctx.helper.mul(newBills.qtcl_qty, newBills.unit_price, tpDecimal);
+                newBills.qtcl_tp = this.ctx.helper.mul(newBills.sjcl_qty, newBills.unit_price, tpDecimal);
+                newBills.total_price = this.ctx.helper.mul(newBills.quantity, newBills.unit_price, tpDecimal);
+                if (defaultData) this.ctx.helper._.assignIn(newBills, defaultData);
+                pbd.push(newBills);
+            }
+            for (const d of pbd) {
+                const parent = pbd.find(function (x) {
+                    return x.ledger_id === d.ledger_pid;
+                });
+                d.full_path = parent
+                    ? parent.full_path + '-' + d.ledger_id
+                    : newParentPath + '-' + d.ledger_id;
+                if (defaultData) this.ctx.helper._.assignIn(pbd, defaultData);
+                pasteBillsData.push(d);
+            }
+            maxId = maxId + pbd.length;
+        }
+
+        this.transaction = await this.db.beginTransaction();
+        try {
+            // 选中节点的所有后兄弟节点,order+粘贴节点个数
+            await this._updateChildrenOrder(tid, selectData.ledger_pid, selectData.order + 1, pasteData.length);
+            // 数据库创建新增节点数据
+            if (pasteBillsData.length > 0) {
+                const newData = await this.transaction.insert(this.tableName, pasteBillsData);
+            }
+            this._cacheMaxLid(tid, maxId);
+            if (pastePosData.length > 0) {
+                await this.transaction.insert(this.ctx.service.pos.tableName, pastePosData);
+            }
+            await this.transaction.commit();
+        } catch (err) {
+            await this.transaction.rollback();
+            throw err;
+        }
+
+        // 查询应返回的结果
+        const updateData = await this.getNextsData(selectData.tender_id, selectData.ledger_pid, selectData.order + pasteData.length);
+        return {
+            ledger: { create: pasteBillsData, update: updateData },
+            pos: pastePosData,
+        };
+    }
 }
 
 module.exports = BaseBillsSerivce;

+ 0 - 3
app/base/base_tree_service.js

@@ -1033,9 +1033,6 @@ class TreeService extends Service {
     async pasteBlock(mid, kid, paste) {
         if ((mid <= 0) || (kid <= 0)) return [];
 
-        console.log(mid);
-        console.log(kid);
-        console.log(paste);
         const selectData = await this.getDataByKid(mid, kid);
         if (!selectData) throw '数据错误';
 

+ 1 - 3
app/controller/change_controller.js

@@ -130,7 +130,6 @@ module.exports = app => {
                 codeRule,
                 dealCode: ctx.tender.info.deal_info.dealCode,
                 auditConst: audit.flow,
-                ledgerConsts: audit.ledger.status,
                 changeConst,
                 ruleType: codeRuleConst.ruleType.change,
                 ruleConst: codeRuleConst.measure,
@@ -271,10 +270,8 @@ module.exports = app => {
 
                 // 根据auditStatus获取审批人列表
                 const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
-
                 // 获取已选清单
                 let changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.params.cid } });
-
                 const renderData = {
                     uid: ctx.session.sessionUser.accountId,
                     tender,
@@ -282,6 +279,7 @@ module.exports = app => {
                     changeConst,
                     auditStatus,
                     auditConst: audit.flow,
+                    ledgerConsts: audit.ledger.status,
                     attList,
                     whiteList,
                     auditList,

+ 1 - 1
app/controller/ledger_controller.js

@@ -226,7 +226,7 @@ module.exports = app => {
             if ((isNaN(data.id) || data.id <= 0) ||
                 (!data.tid && data.tid <= 0) ||
                 (!data.block || data.block.length <= 0)) throw '参数错误';
-            return await ctx.service.ledger.pasteBlock(ctx.tender.id, data.id, { tid: data.tid, block: data.block });
+            return await ctx.service.ledger.pasteBlockData(ctx.tender.id, data.id, data.block);
         }
         /**
          * 从标准项目表添加数据

+ 0 - 1
app/controller/material_controller.js

@@ -156,7 +156,6 @@ module.exports = app => {
                 ctx.redirect('/tender/' + ctx.tender.id + '/measure/material/');
             } catch (err) {
                 this.log(err);
-                console.log(err);
                 ctx.redirect(ctx.request.header.referer);
             }
         }

+ 1 - 1
app/controller/revise_controller.js

@@ -567,7 +567,7 @@ module.exports = app => {
             if ((isNaN(data.id) || data.id <= 0) ||
                 (!data.tid && data.tid <= 0) ||
                 (!data.block || data.block.length <= 0)) throw '参数错误';
-            return await this.ctx.service.revise.pasteBlock(ctx.tender.id, data.id, {tid: data.tid, block: data.block});
+            return await this.ctx.service.reviseBills.pasteBlockData(this.ctx.tender.id, data.id, data.block, {crid: revise.id});
         }
         async _addStd(revise, data) {
             if ((isNaN(data.id) || data.id <= 0) || !data.stdType || !data.stdNode) throw '参数错误';

+ 3 - 2
app/controller/stage_controller.js

@@ -1011,7 +1011,7 @@ module.exports = app => {
                     throw '您无权进行该操作';
                 }
                 const data = JSON.parse(ctx.request.body.data);
-                // data.checkType = parseInt(data.checkType);
+                data.checkType = parseInt(data.checkType);
                 // const data = {
                 //     checkType: parseInt(ctx.request.body.checkType),
                 //     opinion: ctx.request.body.opinion,
@@ -1027,7 +1027,8 @@ module.exports = app => {
 
                 await ctx.service.stageAudit.check(ctx.stage.id, data, ctx.stage.times);
 
-                ctx.body = { err: 0, msg: '', data: [] };// ctx.redirect(ctx.request.header.referer);
+                ctx.body = { err: 0, msg: '', data: [] };
+                // ctx.redirect(ctx.request.header.referer);
             } catch (err) {
                 // console.log(err);
                 this.log(err);

+ 14 - 8
app/public/js/change.js

@@ -184,10 +184,7 @@ $(document).ready(() => {
     $('.ml-auto').on('click', 'a', function () {
         const content = $(this).attr('href');
         if (content === '#add-bj') {
-            if (parseInt(ledger_status) === ledgerConsts.uncheck) {
-                $('#warning-ledger').modal('show');
-            } else {
-                $('#add-bj-modal').modal('show')
+            $('#add-bj-modal').modal('show')
                 getNewCode();
                 if ($('#changeList').children.length === 0) {
                     $('#addCancel').hide();
@@ -195,7 +192,18 @@ $(document).ready(() => {
                     $('#addCancel').show();
                 }
                 $('#bj-code').removeClass('is-invalid');
-            }
+            // if (parseInt(ledger_status) === ledgerConsts.uncheck) {
+            //     $('#warning-ledger').modal('show');
+            // } else {
+            //     $('#add-bj-modal').modal('show')
+            //     getNewCode();
+            //     if ($('#changeList').children.length === 0) {
+            //         $('#addCancel').hide();
+            //     } else {
+            //         $('#addCancel').show();
+            //     }
+            //     $('#bj-code').removeClass('is-invalid');
+            // }
         }
     })
     // 新增变更令 modal显示
@@ -213,9 +221,7 @@ $(document).ready(() => {
     //     }
     //     $('#bj-code').removeClass('is-invalid');
     // });
-    $('#led-warning').click(function () {
-        $('#warning-ledger').modal('hide');
-    })
+
     // 获取最新可用变更令号
     $('#autoCode').click(getNewCode);
     // 新增变更令 确认

+ 7 - 7
app/public/js/change_approval.js

@@ -149,18 +149,18 @@ const postDataWithAsync = function (url, data, successCallback, errorCallBack, s
 };
 
 function auditCheck(i) {
-    console.log('111111111')
     const inlineRadio1 = $('#change-back:checked').val()
     const inlineRadio2 = $('#chagne-backnew:checked').val()
     const opinion = $('textarea[name="sdesc"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
     $('textarea[name="sdesc"]').eq(i).val(opinion);
-    if (!inlineRadio1 && !inlineRadio2) {
-        if (!$('#warning-text').length) {
-            $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+    if (i === 1) {
+        if (!inlineRadio1 && !inlineRadio2) {
+            if (!$('#warning-text').length) {
+                $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+            }
+            return false;
         }
-        return false;
-    } else {
         if ($('#warning-text').length) $('#warning-text').remove()
-        return true;
     }
+    return true;
 }

+ 5 - 4
app/public/js/gcl_gather.js

@@ -415,7 +415,7 @@ const gclGatherModel = (function () {
         for (const c of chapter) {
             const cc = { code: c.code, name: c.name, cType: 1 };
             cc.serialNo = serialNo++;
-            cc.filter = '^[\\D]*' + c.code.substr(0, c.code.length - 2) + '[0-9]{2}-';
+            cc.filter = '^[^0-9]*' + c.code.substr(0, c.code.length - 2) + '[0-9]{2}-';
             gclChapter.push(cc);
         }
         gclChapter.push({ name: '未计入章节清单合计', cType: 21, serialNo: serialNo++, });
@@ -464,11 +464,12 @@ const gclGatherModel = (function () {
             }
         }
         for (const d of deal) {
+            if (!d.quantity || !d.unit_price) continue;
             for (const c of otherChapter) {
-            if (c.cType === 41 || c.cType === 11) {
-                c.deal_bills_tp = ZhCalc.add(c.deal_bills_tp, d.total_price);
+                if (c.cType === 41 || c.cType === 11) {
+                    c.deal_bills_tp = ZhCalc.add(c.deal_bills_tp, d.total_price);
+                }
             }
-        }
             const c = _getGclChapter(gclChapter, d);
             c.deal_bills_tp = ZhCalc.add(c.deal_bills_tp, d.total_price);
         }

+ 10 - 2
app/public/js/ledger.js

@@ -1188,10 +1188,18 @@ $(document).ready(function() {
                     toastr.error('仅可同时选中同层节点');
                     return;
                 }
-                copyBlockList.push(node.ledger_id);
-                iRow += sheet.zh_tree.getPosterity(node).length + 1;
+                const posterity = sheet.zh_tree.getPosterity(node);
+                iRow += posterity.length + 1;
+                posterity.unshift(node);
+                copyBlockList.push(sheet.zh_tree.getDefaultData(posterity));
             }
             const tenderId = _.toInteger(getTenderId());
+            for (const cbl of copyBlockList) {
+                for (b of cbl) {
+                    const posRange = pos.getLedgerPos(b.id);
+                    if (posRange && posRange.length > 0) b.pos = posRange;
+                }
+            }
             setLocalCache(copyBlockTag, JSON.stringify({tid: tenderId, block: copyBlockList}));
             //treeOperationObj.block = copyBlockList;
         },

+ 7 - 6
app/public/js/material_audit.js

@@ -167,13 +167,14 @@ function auditCheck(i) {
     const inlineRadio2 = $('#inlineRadio2:checked').val()
     const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
     $('textarea[name="opinion"]').eq(i).val(opinion);
-    if (!inlineRadio1 && !inlineRadio2) {
-        if (!$('#warning-text').length) {
-            $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+    if (i === 1) {
+        if (!inlineRadio1 && !inlineRadio2) {
+            if (!$('#warning-text').length) {
+                $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+            }
+            return false;
         }
-        return false;
-    } else {
         if ($('#warning-text').length) $('#warning-text').remove()
-        return true;
     }
+    return true;
 }

+ 21 - 0
app/public/js/path_tree.js

@@ -799,6 +799,27 @@ const createNewPathTree = function (type, setting) {
                 });
             }
         };
+
+        _getDefaultNodeData(node) {
+            const result = {};
+            for (const prop in node) {
+                if (['children', 'visible', 'expanded'].indexOf(prop) >= 0) continue;
+                result[prop] = node[prop];
+            }
+            return result;
+        }
+
+        getDefaultData(node) {
+            if (node instanceof Array) {
+                const arr = [];
+                for (const n of node) {
+                    arr.push(this._getDefaultNodeData(n));
+                }
+                return arr;
+            } else {
+                this._getDefaultNodeData(node);
+            }
+        }
     }
 
     class MeasureTree extends BaseTree {

+ 250 - 175
app/public/js/revise.js

@@ -27,6 +27,7 @@ function getExprInfo (field) {
 function transExpr(expr) {
     return $.trim(expr).replace('\t', '').replace('=', '').replace('%', '/100');
 }
+const copyBlockTag = 'zh.calc.copyBlock';
 
 $(document).ready(() => {
     let stdXmj, stdGcl, searchLedger;
@@ -716,8 +717,8 @@ $(document).ready(() => {
                 self.refreshTree(sheet, result);
                 const sel = sheet.getSelections()[0];
                 if (sel) {
-                    sheet.setSelection(tree.nodes.indexOf(refreshData.create[0]), sel.col, sel.rowCount, sel.colCount);
-                    SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(refreshData.create[0])]);
+                    sheet.setSelection(tree.nodes.indexOf(result.create[0]), sel.col, sel.rowCount, sel.colCount);
+                    SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(result.create[0])]);
                 }
                 self.refreshOperationValid(sheet);
                 removeLocalCache(copyBlockTag);
@@ -917,192 +918,263 @@ $(document).ready(() => {
         });
         SpreadJsObj.addDeleteBind(billsSpread, billsTreeSpreadObj.deletePress);
         SpreadJsObj.addCutEvents(billsSpread, billsTreeSpreadObj.cut);
-        let batchInsertObj;
-        $.contextMenu.types.batchInsert = function (item, opt, root) {
-            const self = this;
-            if ($.isFunction(item.icon)) {
-                item._icon = item.icon.call(this, this, $t, key, item);
+    }
+    // 右键菜单
+    let batchInsertObj;
+    $.contextMenu.types.batchInsert = function (item, opt, root) {
+        const self = this;
+        if ($.isFunction(item.icon)) {
+            item._icon = item.icon.call(this, this, $t, key, item);
+        } else {
+            if (typeof(item.icon) === 'string' && item.icon.substring(0, 3) === 'fa-') {
+                // to enable font awesome
+                item._icon = root.classNames.icon + ' ' + root.classNames.icon + '--fa fa ' + item.icon;
             } else {
-                if (typeof(item.icon) === 'string' && item.icon.substring(0, 3) === 'fa-') {
-                    // to enable font awesome
-                    item._icon = root.classNames.icon + ' ' + root.classNames.icon + '--fa fa ' + item.icon;
-                } else {
-                    item._icon = root.classNames.icon + ' ' + root.classNames.icon + '-' + item.icon;
-                }
+                item._icon = root.classNames.icon + ' ' + root.classNames.icon + '-' + item.icon;
             }
-            this.addClass(item._icon);
-            const $obj = $('<div>' + item.name + '<input class="text-right ml-1 mr-1" type="tel" max="20" min="1" value="' + item.value + '" style="width: 30px; height: 18px; padding-right: 4px;">行</div>')
-                .appendTo(this);
-            const $input = $obj.find('input');
-
-            const event = () => {
-                if (self.hasClass('context-menu-disabled')) return;
-                item.batchInsert($input[0], root);
-            };
-            $obj.on('click', event).keypress(function (e) {if (e.keyCode === 13) { event(); }});
-            $input.click((e) => {e.stopPropagation();})
-                .keyup((e) => {if (e.keyCode === 13) item.batchInsert($input[0], root);})
-                .on('input', function () {this.value = this.value.replace(/[^\d]/g, '');});
+        }
+        this.addClass(item._icon);
+        const $obj = $('<div>' + item.name + '<input class="text-right ml-1 mr-1" type="tel" max="20" min="1" value="' + item.value + '" style="width: 30px; height: 18px; padding-right: 4px;">行</div>')
+            .appendTo(this);
+        const $input = $obj.find('input');
+
+        const event = () => {
+            if (self.hasClass('context-menu-disabled')) return;
+            item.batchInsert($input[0], root);
         };
-        // 右键菜单
-        $.contextMenu({
-            selector: '#bills-spread',
-            build: function ($trigger, e) {
-                const target = SpreadJsObj.safeRightClickSelection($trigger, e, billsSpread);
-                return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+        $obj.on('click', event).keypress(function (e) {if (e.keyCode === 13) { event(); }});
+        $input.click((e) => {e.stopPropagation();})
+            .keyup((e) => {if (e.keyCode === 13) item.batchInsert($input[0], root);})
+            .on('input', function () {this.value = this.value.replace(/[^\d]/g, '');});
+    };
+    const billsContextMenuOptions = {
+        selector: '#bills-spread',
+        build: function ($trigger, e) {
+            const target = SpreadJsObj.safeRightClickSelection($trigger, e, billsSpread);
+            return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+        },
+        items: {}
+    };
+    if (!readOnly) {
+        billsContextMenuOptions.items.create = {
+            name: '新增',
+            icon: 'fa-sign-in',
+            callback: function (key, opt) {
+                billsTreeSpreadObj.baseOpr(billsSheet, 'add');
             },
-            items: {
-                'create': {
-                    name: '新增',
-                    icon: 'fa-sign-in',
-                    callback: function (key, opt) {
-                        billsTreeSpreadObj.baseOpr(billsSheet, 'add');
-                    },
-                    disabled: function (key, opt) {
-                        const sheet = billsSheet;
-                        const selection = sheet.getSelections();
-                        const sel = selection ? selection[0] : sheet.getSelections()[0];
-                        const row = sel ? sel.row : -1;
-                        const tree = sheet.zh_tree;
-                        if (!tree) return true;
-                        const first = sheet.zh_tree.nodes[row];
-                        const valid = !sheet.zh_setting.readOnly;
-                        return !(valid && first && first.level > 1);
-                    }
-                },
-                'delete': {
-                    name: '删除',
-                    icon: 'fa-remove',
-                    callback: function (key, opt) {
-                        billsTreeSpreadObj.baseOpr(billsSheet, 'delete');
-                    },
-                    disabled: function (key, opt) {
-                        const sheet = billsSheet;
-                        const selection = sheet.getSelections();
-                        const sel = selection ? selection[0] : sheet.getSelections()[0];
-                        const row = sel ? sel.row : -1;
-                        const tree = sheet.zh_tree;
-                        if (!tree) return true;
-                        const first = sheet.zh_tree.nodes[row];
-                        let last = first, sameParent = true, nodeUsed = first.used;
-                        if (sel.rowCount > 1 && first) {
-                            for (let r = 1; r < sel.rowCount; r++) {
-                                const rNode = tree.nodes[sel.row + r];
-                                if (!rNode) {
-                                    sameParent = false;
-                                    break;
-                                }
-                                nodeUsed = nodeUsed || rNode.used;
-                                if (rNode.level > first.level) continue;
-                                if ((rNode.level < first.level) || (rNode.level === first.level && rNode.pid !== first.pid)) {
-                                    sameParent = false;
-                                    break;
-                                }
-                                last = rNode;
-                            }
+            disabled: function (key, opt) {
+                const sheet = billsSheet;
+                const selection = sheet.getSelections();
+                const sel = selection ? selection[0] : sheet.getSelections()[0];
+                const row = sel ? sel.row : -1;
+                const tree = sheet.zh_tree;
+                if (!tree) return true;
+                const first = sheet.zh_tree.nodes[row];
+                const valid = !sheet.zh_setting.readOnly;
+                return !(valid && first && first.level > 1);
+            }
+        };
+        billsContextMenuOptions.items.delete = {
+            name: '删除',
+            icon: 'fa-remove',
+            callback: function (key, opt) {
+                billsTreeSpreadObj.baseOpr(billsSheet, 'delete');
+            },
+            disabled: function (key, opt) {
+                const sheet = billsSheet;
+                const selection = sheet.getSelections();
+                const sel = selection ? selection[0] : sheet.getSelections()[0];
+                const row = sel ? sel.row : -1;
+                const tree = sheet.zh_tree;
+                if (!tree) return true;
+                const first = sheet.zh_tree.nodes[row];
+                let last = first, sameParent = true, nodeUsed = first.used;
+                if (sel.rowCount > 1 && first) {
+                    for (let r = 1; r < sel.rowCount; r++) {
+                        const rNode = tree.nodes[sel.row + r];
+                        if (!rNode) {
+                            sameParent = false;
+                            break;
                         }
-                        const valid = !sheet.zh_setting.readOnly;
-                        return !(valid && first && sameParent && !(first.level === 1 && first.node_type) && !nodeUsed);
-                    }
-                },
-                'sprBase': '-----------',
-                'batchInsert': {
-                    name: '批量插入',
-                    type: 'batchInsert',
-                    value: '2',
-                    icon: 'fa-sign-in',
-                    batchInsert: function (obj, root) {
-                        if (_.toNumber(obj.value) > _.toNumber(obj.max)) {
-                            obj.value = obj.max;
-                            toastr.warning('批量插入不可多于' + obj.max);
-                        } else if (_.toNumber(obj.value) < _.toNumber(obj.min)) {
-                            obj.value = obj.min;
-                            toastr.warning('批量插入不可少于' + obj.min);
-                        } else {
-                            billsTreeSpreadObj.baseOpr(billsSheet, 'add', parseInt(obj.value));
-                            root.$menu.trigger('contextmenu:hide');
+                        nodeUsed = nodeUsed || rNode.used;
+                        if (rNode.level > first.level) continue;
+                        if ((rNode.level < first.level) || (rNode.level === first.level && rNode.pid !== first.pid)) {
+                            sameParent = false;
+                            break;
                         }
-                    },
-                    disabled: function (key, opt) {
-                        const sheet = billsSheet;
-                        const selection = sheet.getSelections();
-                        const sel = selection ? selection[0] : sheet.getSelections()[0];
-                        const row = sel ? sel.row : -1;
-                        const tree = sheet.zh_tree;
-                        if (!tree) return true;
-                        const first = sheet.zh_tree.nodes[row];
-                        const valid = !sheet.zh_setting.readOnly;
-                        return !(valid && first && first.level > 1);
+                        last = rNode;
                     }
-                },
-                'batchInsertBillsPos': {
-                    name: '批量插入清单-计量单元',
-                    icon: 'fa-sign-in',
-                    disabled: function (key, opt) {
-                        if (!isTz) return true;
-                        const select = SpreadJsObj.getSelectObject(billsSheet);
-                        if (select) {
-                            if (select.code && select.code !== '') {
-                                return !billsTree.isLeafXmj(select);
-                            } else {
-                                const parent = billsTree.getParent(select);
-                                return !(parent && billsTree.isLeafXmj(parent));
-                            }
-                        } else {
-                            return false;
-                        }
-                    },
-                    callback: function (key, opt) {
-                        if (!batchInsertObj) {
-                            batchInsertObj = new BatchInsertBillsPosObj($('#batch'));
-                        } else {
-                            batchInsertObj.initView();
-                        }
-                        $('#batch').modal('show');
+                }
+                const valid = !sheet.zh_setting.readOnly;
+                return !(valid && first && sameParent && !(first.level === 1 && first.node_type) && !nodeUsed);
+            }
+        };
+        billsContextMenuOptions.items.sprBase = '-----------';
+    }
+    billsContextMenuOptions.items.copyBlock = {
+        name: '复制整块',
+        icon: 'fa-files-o',
+        callback: function (key, opt) {
+            const copyBlockList = [];
+            const sheet = billsSheet;
+            const sel = sheet.getSelections()[0];
+            let iRow = sel.row;
+            const pid = sheet.zh_tree.nodes[iRow].ledger_pid;
+            while (iRow < sel.row + sel.rowCount) {
+                const node = sheet.zh_tree.nodes[iRow];
+                if (node.ledger_pid !== pid) {
+                    toastr.error('仅可同时选中同层节点');
+                    return;
+                }
+                const posterity = sheet.zh_tree.getPosterity(node);
+                iRow += posterity.length + 1;
+                posterity.unshift(node);
+                copyBlockList.push(sheet.zh_tree.getDefaultData(posterity));
+            }
+            const tenderId = _.toInteger(getTenderId());
+            for (const cbl of copyBlockList) {
+                const posRange = pos.getLedgerPos(cbl.id);
+                if (posRange && posRange.length > 0) cbl.pos = posRange;
+            }
+            setLocalCache(copyBlockTag, JSON.stringify({tid: tenderId, block: copyBlockList}));
+        },
+        visible: function (key, opt) {
+            const sheet = billsSheet;
+            const selection = sheet.getSelections();
+            const row = selection[0].row;
+            const select = billsTree.nodes[row];
+            return select;
+        },
+        disabled: function (key, opt) {
+            const sheet = billsSheet;
+            const selection = sheet.getSelections();
+            const row = selection[0].row;
+            const select = billsTree.nodes[row];
+            return select && select.level <= 1;
+        }
+    };
+    if (!readOnly) {
+        billsContextMenuOptions.items.pasteBlock = {
+            name: '粘贴整块',
+            icon: 'fa-clipboard',
+            disabled: function (key, opt) {
+                //const block = treeOperationObj.block || [];
+                const copyInfo = JSON.parse(getLocalCache(copyBlockTag));
+                return !(copyInfo && copyInfo.tid && copyInfo.tid > 0 && copyInfo.block && copyInfo.block.length > 0);
+            },
+            callback: function (key, opt) {
+                //const block = treeOperationObj.block || [];
+                const copyInfo = JSON.parse(getLocalCache(copyBlockTag));
+                if (copyInfo.block.length > 0) {
+                    billsTreeSpreadObj.pasteBlock(billsSpread, copyInfo);
+                } else {
+                    document.execCommand('paste');
+                }
+            },
+            visible: function (key, opt) {
+                return !readOnly;
+            }
+        };
+        billsContextMenuOptions.items.sprBlock = '-----------';
+    }
+    if (!readOnly) {
+        billsContextMenuOptions.items.batchInsert = {
+            name: '批量插入',
+            type: 'batchInsert',
+            value: '2',
+            icon: 'fa-sign-in',
+            batchInsert: function (obj, root) {
+                if (_.toNumber(obj.value) > _.toNumber(obj.max)) {
+                    obj.value = obj.max;
+                    toastr.warning('批量插入不可多于' + obj.max);
+                } else if (_.toNumber(obj.value) < _.toNumber(obj.min)) {
+                    obj.value = obj.min;
+                    toastr.warning('批量插入不可少于' + obj.min);
+                } else {
+                    billsTreeSpreadObj.baseOpr(billsSheet, 'add', parseInt(obj.value));
+                    root.$menu.trigger('contextmenu:hide');
+                }
+            },
+            disabled: function (key, opt) {
+                const sheet = billsSheet;
+                const selection = sheet.getSelections();
+                const sel = selection ? selection[0] : sheet.getSelections()[0];
+                const row = sel ? sel.row : -1;
+                const tree = sheet.zh_tree;
+                if (!tree) return true;
+                const first = sheet.zh_tree.nodes[row];
+                const valid = !sheet.zh_setting.readOnly;
+                return !(valid && first && first.level > 1);
+            }
+        };
+        billsContextMenuOptions.items.batchInsertBillsPos = {
+            name: '批量插入清单-计量单元',
+            icon: 'fa-sign-in',
+            disabled: function (key, opt) {
+                if (!isTz) return true;
+                const select = SpreadJsObj.getSelectObject(billsSheet);
+                if (select) {
+                    if (select.code && select.code !== '') {
+                        return !billsTree.isLeafXmj(select);
+                    } else {
+                        const parent = billsTree.getParent(select);
+                        return !(parent && billsTree.isLeafXmj(parent));
                     }
-                },
-                'sprBatch': '-----------',
-                'importGclBills2Xmj': {
-                    name: '导入工程量清单至项目节',
-                    icon: 'fa-file-excel-o',
-                    disabled: function (key, opt) {
-                        const node = SpreadJsObj.getSelectObject(billsSheet);
-                        return readOnly
-                            || (node.children && node.children.length > 0)
-                            || (!_.isNil(node.b_code) && node.b_code !== '')
-                            || billsTree.checkNodeUsed(node, pos);
+                } else {
+                    return false;
+                }
+            },
+            callback: function (key, opt) {
+                if (!batchInsertObj) {
+                    batchInsertObj = new BatchInsertBillsPosObj($('#batch'));
+                } else {
+                    batchInsertObj.initView();
+                }
+                $('#batch').modal('show');
+            }
+        };
+        billsContextMenuOptions.items.sprBatch = '-----------';
+        billsContextMenuOptions.items.importGclBills2Xmj = {
+            name: '导入工程量清单至项目节',
+            icon: 'fa-file-excel-o',
+            disabled: function (key, opt) {
+                const node = SpreadJsObj.getSelectObject(billsSheet);
+                return readOnly
+                    || (node.children && node.children.length > 0)
+                    || (!_.isNil(node.b_code) && node.b_code !== '')
+                    || billsTree.checkNodeUsed(node, pos);
+            },
+            callback: function (key, opt) {
+                const node = SpreadJsObj.getSelectObject(billsSheet);
+                importExcel.doImport({
+                    template: {
+                        hint: '工程量清单',
+                        url: '/template/导入工程量清单EXCEL格式.xls',
                     },
-                    callback: function (key, opt) {
-                        const node = SpreadJsObj.getSelectObject(billsSheet);
-                        importExcel.doImport({
-                            template: {
-                                hint: '工程量清单',
-                                url: '/template/导入工程量清单EXCEL格式.xls',
-                            },
-                            callback: function (sheet) {
-                                postDataCompress(window.location.pathname + '/upload-excel/gcl2xmj', {id: node.id, sheet: sheet}, function (result) {
-                                    const sel = billsSheet.getSelections();
-
-                                    const refreshNode = billsTree.loadPostData(result);
-                                    billsTreeSpreadObj.refreshTree(billsSheet, refreshNode);
-                                    if (refreshNode.create[0]) {
-                                        if (sel && sel[0]) {
-                                            billsSheet.setSelection(refreshNode.create[0].index, sel[0].col, sel[0].rowCount, sel[0].colCount);
-                                            SpreadJsObj.reloadRowsBackColor(billsSheet, [sel[0].row, refreshNode.create[0].index]);
-                                        } else {
-                                            billsSheet.setSelection(refreshNode.create[0].index, 0, 1, 1);
-                                            SpreadJsObj.reloadRowsBackColor(billsSheet, [refreshNode.create[0].index]);
-                                        }
-                                    }
-                                    billsTreeSpreadObj.refreshOperationValid(billsSheet);
-                                }, null);
+                    callback: function (sheet) {
+                        postDataCompress(window.location.pathname + '/upload-excel/gcl2xmj', {id: node.id, sheet: sheet}, function (result) {
+                            const sel = billsSheet.getSelections();
+
+                            const refreshNode = billsTree.loadPostData(result);
+                            billsTreeSpreadObj.refreshTree(billsSheet, refreshNode);
+                            if (refreshNode.create[0]) {
+                                if (sel && sel[0]) {
+                                    billsSheet.setSelection(refreshNode.create[0].index, sel[0].col, sel[0].rowCount, sel[0].colCount);
+                                    SpreadJsObj.reloadRowsBackColor(billsSheet, [sel[0].row, refreshNode.create[0].index]);
+                                } else {
+                                    billsSheet.setSelection(refreshNode.create[0].index, 0, 1, 1);
+                                    SpreadJsObj.reloadRowsBackColor(billsSheet, [refreshNode.create[0].index]);
+                                }
                             }
-                        });
+                            billsTreeSpreadObj.refreshOperationValid(billsSheet);
+                        }, null);
                     }
-                },
+                });
             }
-        });
+        };
     }
+    $.contextMenu(billsContextMenuOptions);
+
     // 计量单元 相关方法&绑定spreadjs事件
     const posSpreadObj = {
         refreshOperationValid: function (sheet, selection) {
@@ -1951,6 +2023,7 @@ $(document).ready(() => {
 
             $('#batch-ok').click(function () {
                 const selection = billsSheet.getSelections();
+                const sel = selection[0];
                 const row = selection[0].row;
                 const select = billsTree.nodes[row];
                 if (select) {
@@ -1967,6 +2040,8 @@ $(document).ready(() => {
                             pos.updateDatas(data.pos);
                             const result = billsTree.loadPostData(data.ledger);
                             billsTreeSpreadObj.refreshTree(billsSheet, result);
+                            billsSheet.setSelection(result.create[0].index, sel.col, sel.rowCount, sel.colCount);
+                            SpreadJsObj.reloadRowsBackColor(billsSheet, [sel.row, result.create[0].index]);
                             billsTreeSpreadObj.refreshOperationValid(billsSheet, selection);
                             posSpreadObj.loadCurPosData();
                             self.obj.modal('hide');

+ 12 - 2
app/public/js/stage.js

@@ -114,9 +114,13 @@ function getAllList(currPageNum = 1) {
     const currPageAttData = attData.slice((currPageNum-1)*pageCount, currPageNum*pageCount);
     let html = '';
     for(const att of currPageAttData) {
-        html += '<tr><td><a href="javascript:void(0)" file-id="'+ att.id +'">'+ att.filename + att.fileext +'</a></td><td>'+ att.username +'</td></tr>';
+        html += '<tr ><td><a href="javascript:void(0)" file-id="'+ att.id +'">'+ att.filename + att.fileext +'</a></td><td>'+ att.username +'</td></tr>';
     }
     $('#alllist-table').html(html);
+    $('#alllist-table').on('click', 'tr', function() {
+        $('#alllist-table tr').removeClass('bg-light')
+        $(this).addClass('bg-light')
+    })
 }
 // 生成当前节点列表
 function getNodeList(node) {
@@ -124,10 +128,13 @@ function getNodeList(node) {
     for(const att of attData) {
         if (node === att.lid) {
             html += '<tr><td><a href="javascript:void(0)" file-id="'+ att.id +'">'+ att.filename + att.fileext +'</a></td><td>'+ att.username +'</td></tr>';
-
         }
     }
     $('#nodelist-table').html(html);
+    $('#nodelist-table').on('click', 'tr', function() {
+        $('#nodelist-table tr').removeClass('bg-light')
+        $(this).addClass('bg-light')
+    })
 }
 
 $(document).ready(() => {
@@ -3061,6 +3068,9 @@ $(document).ready(() => {
                 // 审核被退回,原报上传的附件可以删除
                 if (stage.status === auditConst.status.checkNo && parseInt(cur_uid) !== stage.user_id) showDel = false;
 
+                // 审核中,原报上传的图片不能删除
+                if (stage.status === auditConst.status.checking && stage.user_id === parseInt(cur_uid)) showDel = false;
+
                 // 台账未上报、当前用户为原报, 可以删除附件
                 if (stage.status === auditConst.status.uncheck && stage.user_id !== parseInt(cur_uid)) showDel = false;
 

+ 11 - 2
app/public/js/stage_audit.js

@@ -164,7 +164,16 @@ function checkAuditorFrom () {
 }
 // texterea换行
 function auditCheck(i) {
-    const opinion = $('textarea[name="opinion"]').eq(i).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' ');
-    $('textarea[name="opinion"]').eq(i).val(opinion);
+    const inlineRadio1 = $('#inlineRadio1:checked').val()
+    const inlineRadio2 = $('#inlineRadio2:checked').val()
+    if (i === 1) {
+        if (!inlineRadio1 && !inlineRadio2) {
+            if (!$('#warning-text').length) {
+                $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+            }
+            return false;
+        }
+        if ($('#warning-text').length) $('#warning-text').remove()
+    }
     return true;
 }

+ 3 - 0
app/service/ledger.js

@@ -373,6 +373,8 @@ module.exports = app => {
                     }
                     for (const data of datas) {
                         delete data.children;
+                        delete data.crid;
+                        delete data.is_tp;
                         const p = datas.find(function (x) {
                             return x.ledger_id === data.ledger_pid;
                         });
@@ -392,6 +394,7 @@ module.exports = app => {
                     const posData = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: paste.tid, lid: id.org } });
                     if (posData.length > 0) {
                         for (const pd of posData) {
+                            delete pd.crid;
                             pd.id = this.uuid.v4();
                             pd.lid = id.new;
                             pd.tid = this.ctx.tender.id;

+ 22 - 1
app/view/change/bills_modal.ejs

@@ -207,4 +207,25 @@
             </div>
         </div>
     </div>
-</div>
+</div>
+
+<div class="modal fade" id="warning-ledger" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">警告</h5>
+            </div>
+            <div class="modal-body">
+                <h5>请先上报审批台账,再上报审批变更令。</h5>
+            </div>
+            <div class="modal-footer">
+                <button id="led-warning" class="btn btn-danger btn-sm">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $('#led-warning').click(function () {
+        $('#warning-ledger').modal('hide');
+    });
+</script>

+ 21 - 1
app/view/change/file_modal.ejs

@@ -43,4 +43,24 @@
             </div>
         </div>
     </div>
-</div>
+</div>
+<div class="modal fade" id="warning-ledger" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">警告</h5>
+            </div>
+            <div class="modal-body">
+                <h5>请先上报审批台账,再上报审批变更令。</h5>
+            </div>
+            <div class="modal-footer">
+                <button id="led-warning" class="btn btn-danger btn-sm">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    $('#led-warning').click(function () {
+        $('#warning-ledger').modal('hide');
+    });
+</script>

+ 0 - 3
app/view/change/index.ejs

@@ -80,9 +80,6 @@
         </div>
     </div>
 </div>
-<script>
-    const tendetStatus = '<%- tender %>'
-</script>
 <script src="/public/js/sub_menu.js"></script>
 <script>
     $.subMenu({

+ 9 - 0
app/view/change/info.ejs

@@ -736,7 +736,16 @@
     const totalPriceUnit = '<%- tpUnit %>';
     const unitPriceUnit = '<%- upUnit %>';
     const accountId = '<%- uid %>';
+    const ledgeStatus = '<%- tender.ledger_status %>';
+    const ledgerConsts = JSON.parse('<%- JSON.stringify(ledgerConsts) %>');
     autoFlashHeight();
+    $('a[href="#sub-ap"').click(function() {
+        if (parseInt(ledgeStatus) === ledgerConsts.uncheck) {
+            $('#warning-ledger').modal('show');
+            return false
+        }
+    });
+
 </script>
 <script src="/public/js/datatable/jquery.dataTables.min.js"></script>
 <script src="/public/js/datatable/dataTables.bootstrap4.min.js"></script>

+ 30 - 0
app/view/change/info_modal.ejs

@@ -789,3 +789,33 @@
     </div>
 </div>
 <% } %>
+
+<div class="modal fade" id="warning-ledger" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">警告</h5>
+            </div>
+            <div class="modal-body">
+                <h5>请先上报审批台账,再上报审批变更令。</h5>
+            </div>
+            <div class="modal-footer">
+                <button id="led-warning" class="btn btn-danger btn-sm">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $('.modal').on('shown.bs.modal', function () {
+        const height = $(this)[0].scrollHeight
+        const scrollBox = $(this).find('div[class="col-8 modal-height-500"]')
+        // 450是modal没有滚动条时的最大高度,超过则出现滚动条,需要自动下拉到底部
+        if (scrollBox.length && scrollBox[0].scrollHeight > 450) {
+            scrollBox.scrollTop(height);
+        }
+    });
+    $('#led-warning').click(function () {
+        $('#warning-ledger').modal('hide');
+    });
+</script>

+ 0 - 18
app/view/change/modal.ejs

@@ -18,22 +18,6 @@
     </div>
 </div>
 
-<div class="modal fade" id="warning-ledger" data-backdrop="static">
-    <div class="modal-dialog" role="document">
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title">警告</h5>
-            </div>
-            <div class="modal-body">
-                <h5>请先上报审批台账,再上报审批变更令。</h5>
-            </div>
-            <div class="modal-footer">
-                <button id="led-warning" class="btn btn-danger btn-sm">确定</button>
-            </div>
-        </div>
-    </div>
-</div>
-
 <% if (tender.user_id === uid) { %>
 <!--弹出添加变更令-->
 <div class="modal fade" id="add-bj-modal" data-backdrop="static">
@@ -150,8 +134,6 @@
     let codeRule = JSON.parse('<%- JSON.stringify(codeRule) %>');
     let connectorRule = '<%- tender.c_connector %>';
     let cRuleFirst = '<%- tender.c_rule_first %>';
-    const ledger_status = '<%- JSON.stringify(tender.ledger_status) %>';
-    const ledgerConsts = JSON.parse('<%- JSON.stringify(ledgerConsts) %>');
 </script>
 <script src="/public/js/moment/moment.min.js"></script>
 

+ 8 - 2
app/view/material/audit_modal.ejs

@@ -867,6 +867,12 @@
 <% } %>
 
 <script>
-    const au = JSON.parse('<%- JSON.stringify(ctx.material.auditHistory) %>');
-    console.log(au);
+    $('.modal').on('shown.bs.modal', function () {
+        const height = $(this)[0].scrollHeight
+        const scrollBox = $(this).find('div[class="col-8 modal-height-500"]')
+        // 450是modal没有滚动条时的最大高度,超过则出现滚动条,需要自动下拉到底部
+        if (scrollBox.length && scrollBox[0].scrollHeight > 450) {
+            scrollBox.scrollTop(height);
+        }
+    });
 </script>

+ 1 - 1
app/view/measure/audit_modal.ejs

@@ -106,4 +106,4 @@
         </div>
     </div>
 </div>
-<% } %>
+<% } %>

+ 30 - 12
app/view/stage/audit_modal.ejs

@@ -104,7 +104,7 @@
                                     </ul>
                                 </div>
                             </div>
-                            <div class="col-8 modal-height-500" style="overflow: auto">
+                            <div class="col-8 modal-height-500" style="overflow: auto" >
                                 <% for (const ah of ctx.stage.auditHistory) { %>
                                     <div class="card mt-3">
                                         <ul class="list-group list-group-flush">
@@ -238,7 +238,7 @@
         <!--审批退回-->
         <div class="modal fade" id="sp-back" data-backdrop="static">
             <div class="modal-dialog modal-lg" role="document">
-                <form class="modal-content modal-lg" action="<%- preUrl %>/audit/check" method="post" id="audit-check1">
+                <form class="modal-content modal-lg" action="<%- preUrl %>/audit/check" method="post" id="audit-check1" >
                     <div class="modal-header">
                         <h5 class="modal-title">审批退回</h5>
                     </div>
@@ -380,15 +380,17 @@
                                                         <label>审批意见<b class="text-danger">*</b></label>
                                                         <textarea class="form-control form-control-sm" name="opinion">不同意</textarea>
                                                     </div>
-                                                    <div class="alert alert-warning">
+                                                    <div id="reject-process" class="alert alert-warning">
                                                         <div class="form-check form-check-inline">
-                                                            <input class="form-check-input" type="radio" name="checkType" id="inlineRadio1" value="<%- auditConst.status.checkNo %>" <% if (auditors[iA].order === 1 || auditors[iA].aid === auditors[0].aid) { %>checked<% } %>>
+                                                            <!-- <input class="form-check-input" type="radio" name="checkType" id="inlineRadio1" value="<%- auditConst.status.checkNo %>" <% if (auditors[iA].order === 1 || auditors[iA].aid === auditors[0].aid) { %>checked<% } %>> -->
+                                                            <input class="form-check-input" type="radio" name="checkType" id="inlineRadio1" value="<%- auditConst.status.checkNo %>">
                                                             <label class="form-check-label" for="inlineRadio1">退回原报 <%- ctx.stage.user.name %></label>
                                                         </div>
                                                         <% if (auditors[iA].order > 1 && auditors[iA].aid !== auditors[0].aid) { %>
                                                             <% const auditorIndex = ctx.stage.auditors2.findIndex(function (item) { return item.aid === auditors[iA].aid }) %>
                                                             <div class="form-check form-check-inline">
-                                                                <input class="form-check-input" type="radio" name="checkType" id="inlineRadio2" value="<%- auditConst.status.checkNoPre %>" checked>
+                                                                <input class="form-check-input" type="radio" name="checkType" id="inlineRadio2" value="<%- auditConst.status.checkNoPre %>">
+                                                                <!-- <input class="form-check-input" type="radio" name="checkType" id="inlineRadio2" value="<%- auditConst.status.checkNoPre %>" checked> -->
                                                                 <label class="form-check-label" for="inlineRadio2">退回上一审批人 <%- ctx.stage.auditors2[auditorIndex-1].name %></label>
                                                             </div>
                                                         <% } %>
@@ -411,7 +413,7 @@
         </div>
     <% } else { %>
         <!--审批流程/结果-->
-        <div class="modal fade" id="sp-list" data-backdrop="static">
+        <div class="modal fade" id="sp-list" data-backdrop="static" >
             <div class="modal-dialog modal-lg" role="document">
                 <div class="modal-content">
                     <div class="modal-header">
@@ -437,7 +439,7 @@
                                     </ul>
                                 </div>
                             </div>
-                            <div class="col-8 modal-height-500" style="overflow: auto">
+                            <div class="col-8 modal-height-500" style="overflow: auto" >
                                 <% for (const ah of ctx.stage.auditHistory) { %>
                                     <div class="card mt-3">
                                         <ul class="list-group list-group-flush">
@@ -591,7 +593,7 @@
                                 </ul>
                             </div>
                         </div>
-                        <div class="col-8 modal-height-500" style="overflow: auto">
+                        <div class="col-8 modal-height-500" style="overflow: auto" id="scroll-box">
                             <% for (const ah of ctx.stage.auditHistory) { %>
                                 <div class="card mt-3">
                                     <ul class="list-group list-group-flush">
@@ -1530,16 +1532,24 @@
     });
     <% } %>
     $('#audit-check1').submit(function (e) {
-        $(this).parent().parent().modal('hide');
+        // $(this).parent().parent().modal('hide');
         const data = {
             opinion: $('[name=opinion]', this).val().replace(/\r\n/g, '<br/>').replace(/\n/g, '<br/>').replace(/\s/g, ' '),
             checkType: parseInt($('[name=checkType]:checked', this).val()),
         };
-        postData(this.action, data, function () {
+        if (!parseInt($('[name=checkType]:checked', this).val())) {
+            if (!$('#warning-text').length) {
+                $('#reject-process').prepend('<p id="warning-text" style="color: red; margin: 0;">请选择退回流程</p>');
+            }
+            return false;
+        } else {
+            postData(this.action, data, function () {
             window.location.reload();
         });
-        $('#hide-all').hide();
-        return false;
+        }
+        return false
+        // if ($('#warning-text').length) $('#warning-text').remove()
+
     });
     $('#audit-check3').submit(function (e) {
         $(this).parent().parent().modal('hide');
@@ -1553,4 +1563,12 @@
         $('#hide-all').hide();
         return false;
     });
+    $('.modal').on('shown.bs.modal', function () {
+        const height = $(this)[0].scrollHeight
+        const scrollBox = $(this).find('div[class="col-8 modal-height-500"]')
+        // 450是modal没有滚动条时的最大高度,超过则出现滚动条,需要自动下拉到底部
+        if (scrollBox.length && scrollBox[0].scrollHeight > 450) {
+            scrollBox.scrollTop(height);
+        }
+    });
 </script>